2016-11-26 135 views
-1

我經常寫for循環即完成下列工作:通過一個行標識符像家庭號碼有關家庭從 提取值,如果條件滿足

  • 提取信息的值

    1. 週期其他變量
    2. 現在保存在本地宏

    信息我這樣做似乎效率不高和不雅的方式。以下示例說明了我的方法,其中涉及創建一個新變量並對每次迭代中的數據進行排序。

    sysuse auto 
    gen obs_id = _n 
    
    foreach i of numlist 1/74{ 
        *Create variable to get observation to row 1 
        gen temp = 1 if obs_id == `i' 
        sort temp 
    
        *Extract information 
        local w = weight[1] 
        local ma = make[1] 
    
        *Do something with the macros 
        drop temp 
    } 
    

    有時候,我這樣做是與所有的數值變量,所以我用

    sum weight if obs_id == `i' 
    local w = r(mean) 
    

    循環代替,這是較爲有效的內部。

    但是有沒有一種方法可以以比這更明智的方式從變量中保存信息?

    編輯補充: 由於威廉的回答表明,我的意圖是通過觀察的一個子集進行排序,通過一些虛擬變量(即治療= 1)確定的子集。但是,即使這可以通過威廉的基本邏輯處理,具體如下:

    sysuse auto 
    set seed 1234 
    gen random = uniform() 
    gen treat = 0 
    replace treat = 1 if random > 0.7 
    
    sum treat if treat == 1 
    local n = r(N) 
    
    bysort treat: gen counter = _n if treat == 1 
    sort counter 
    
    foreach i of numlist 1/`n'{ 
        local w = weight[`i'] 
        local ma = make[`i'] 
        display `"treated unit `i' - `w' `ma' "' 
    } 
    
  • +0

    我很少遇到我必須通過觀察循環的情況。我可以使用'by variable:egen'完成大部分繁瑣的工作。例如,您可以爲另一個變量的每個值獲取變量的平均值,總和,計數等。您也可以使用'mkmat'和'svmat'從變量創建矩陣,反之亦然,然後使用矩陣運算符。 – chan1142

    +0

    我不明白你爲什麼認爲你需要一個循環,即使你編輯的問題。給定一個二進制變量'treat'以某種方式創建,你的代碼基本上等同於'list weight make if treat == 1'加上一些重複的文本。如果計數器很重要,你可以'生成',單獨添加到'list',但即使如此,本地宏和循環在這裏完全是可有可無的。我猜你對於需要循環的語言更熟悉,但在Stata中,它們通常不需要用於基本任務。 –

    +0

    @Nick,我的實際使用比簡單列出一些值更復雜一點,但我想保持簡單。這就是爲什麼在我最初的例子中,我所說的只是「用宏做些事情」。爲了不從我的問題的核心中分心,我大大簡化了示例,以便我可以使用已發佈的自動數據集,不需要讀者安裝用戶編寫的命令,也不需要解釋30行以上代碼的邏輯循環,當那些東西實際上不是我的問題需要.. – Amberopolis

    回答

    2

    你舉的例子處理每一行中的數據集。假設這就是你想要對你的真實數據做的事情(但是我懷疑你實際上是想處理obs_id值的一個小列表的觀察結果),下面更直接地實現了這一點。

    sysuse auto, clear 
    forvalues i = 1/`= _N' { 
        local w = weight[`i'] 
        local ma = make[`i'] 
        display `"observation `i' - `w' `ma' "' 
    } 
    

    這可以進一步簡化爲

    sysuse auto, clear 
    forvalues i = 1/`= _N' { 
        display `"observation `i' - `= weight[`i']' `=make[`i']' "' 
        } 
    
    +0

    要增加William的有用答案,讓我強調一點,你根本不需要變量'temp'。事實上,你根本不需要任何循環。 '列表重量make'在這裏基本上是等價的。 –

    +0

    @William,你是對的,我打算循環觀察的一個子集。但考慮到這一點,我無法想出一個解決方案(遍歷所有obs)或我的編輯解決方案(通過子集)無法工作的場景。感謝您幫助澄清我的想法! – Amberopolis

    0

    這個答案是強調我的意見是,OP的循環是完全可以避免的。

    (如果它在某種程度上需要一次又一次地看到文字treated unit,然後generate text = "treated unit"並將其包含在list

    sysuse auto, clear 
    set seed 1234 
    gen random = uniform() 
    gen treat = 0 
    replace treat = 1 if random > 0.7 
    sum treat if treat == 1 
    local n = r(N) 
    bysort treat: gen counter = _n if treat == 1 
    sort counter 
    
    * OP's method 
    
    foreach i of numlist 1/`n'{ 
        local w = weight[`i'] 
        local ma = make[`i'] 
        display `"treated unit `i' - `w' `ma' "' 
    } 
    
    treated unit 1 - 3670 Buick LeSabre 
    treated unit 2 - 4330 Cad. Deville 
    treated unit 3 - 3400 Buick Skylark 
    treated unit 4 - 3180 Chev. Malibu 
    treated unit 5 - 2930 AMC Concord 
    treated unit 6 - 2690 Pont. Sunbird 
    treated unit 7 -Pont. Grand Prix 
    treated unit 8 - 2200 Plym. Horizon 
    treated unit 9 - 2070 Audi Fox 
    treated unit 10 - 2640 AMC Spirit 
    treated unit 11 - 3720 Merc. Marquis 
    treated unit 12 - 2110 Chev. Chevette 
    treated unit 13 - 3690 Olds Delta 88 
    treated unit 14 - 3600 Dodge Magnum 
    treated unit 15 - 4060 Merc. Cougar 
    treated unit 16 - 3420 Pont. Phoenix 
    treated unit 17 - 3260 Plym. Arrow 
    treated unit 18 - 2130 Fiat Strada 
    treated unit 19 - 3200 Pont. Le Mans 
    treated unit 20 - 2410 Toyota Celica 
    treated unit 21 - 2670 Toyota Corona 
    treated unit 22 - 2230 Buick Opel 
    treated unit 23 - 3250 Buick Century 
    treated unit 24 - 1800 Plym. Champ 
    treated unit 25 - 2730 Olds Starfire 
    treated unit 26 - 3280 Buick Regal 
    treated unit 27 - 1800 Ford Fiesta 
    treated unit 28 - 1830 Renault Le Car 
    
    * alternative 
    
    list weight make if treat 
    
        +---------------------------+ 
        | weight make    | 
        |---------------------------| 
        1. | 3,670 Buick LeSabre | 
        2. | 4,330 Cad. Deville  | 
        3. | 3,400 Buick Skylark | 
        4. | 3,180 Chev. Malibu  | 
        5. | 2,930 AMC Concord  | 
        |---------------------------| 
        6. | 2,690 Pont. Sunbird | 
        7. | 3,210 Pont. Grand Prix | 
        8. | 2,200 Plym. Horizon | 
        9. | 2,070 Audi Fox   | 
    10. | 2,640 AMC Spirit  | 
        |---------------------------| 
    11. | 3,720 Merc. Marquis | 
    12. | 2,110 Chev. Chevette | 
    13. | 3,690 Olds Delta 88 | 
    14. | 3,600 Dodge Magnum  | 
    15. | 4,060 Merc. Cougar  | 
        |---------------------------| 
    16. | 3,420 Pont. Phoenix | 
    17. | 3,260 Plym. Arrow  | 
    18. | 2,130 Fiat Strada  | 
    19. | 3,200 Pont. Le Mans | 
    20. | 2,410 Toyota Celica | 
        |---------------------------| 
    21. | 2,670 Toyota Corona | 
    22. | 2,230 Buick Opel  | 
    23. | 3,250 Buick Century | 
    24. | 1,800 Plym. Champ  | 
    25. | 2,730 Olds Starfire | 
        |---------------------------| 
    26. | 3,280 Buick Regal  | 
    27. | 1,800 Ford Fiesta  | 
    28. | 1,830 Renault Le Car | 
        +---------------------------+ 
    

    當然,我很高興地認爲,這個玩具問題對於OP的代理真正的問題,但我看不到任何暗示這種技術是好的編程。