首页 > 解决方案 > 如何在Stata中为每行执行不同组的操作

问题描述

假设我有这些数据:

clear all
input n str6 G1 str6 G2 v desired computed
1 "B" "A" 1 5 .
2 "A" "A" 2 5.5 .
3 "C" "A" 3 4.5 .
4 "A" "B" 4 2 .
5 "B" "B" 5 2.5 .
6 "C" "B" 6 1.5 .
end

n是观察数,G1是第 1 组,G2是第 2 组(例如第 1 类和第 2 类),并且v是值。desired是期望的输出,并且computed将是期望的输出的尝试。

我的目标是在Stata中执行一个操作,在这个例子中是一个平均值,对所有与观察没有接触的观察,包括观察本身——即与观察不同G1或不同G2的观察观察(或者是那个观察)。例如,v观测值 1 将是v观测值 4 和 6 的值之和。(1、2 和 3 被排除,因为它们与G21 共享相同。5 也被排除,因为它与G11 共享相同。)因此,我们将v观察值 4 和 6相加,4+6=10然后除以数字 2,得到5

我想我可以用下面的代码得到我想要的:

local N = _N
forvalues i = 1/`N' {
    preserve
    *create temp, which, when equal to 1, indicates the observations to make the calculation on
    gen temp = 1
    *save locals equal to the first and second group of `i'
    local temp_G1 = G1[`i']
    local temp_G2 = G2[`i'] 
    *make temp = 0 for observations that were in first and/or second group as `i'
    replace temp = 0 if G1=="`temp_G1'"
    replace temp = 0 if G2=="`temp_G2'"
    *compute sum on observations that have a temp equal to 1
    egen sum = sum(v) if temp==1
    *fill in the sum for all obs
    egen sum_all = max(sum)
    *compute number in group
    egen num = total(temp) if temp==1
    display "`num'"
    egen num_all = max(num)
    *save the value of the sum in a local
    local calc = sum_all[`i']/num_all[`i']
    restore
    *fill in the value from the local for row `i'
    replace computed = `calc' in `i'
}

但是,这种方法似乎很冗长且不雅。在Stata中有没有更好的方法来解决这个问题?我想过使用bys,但我无法弄清楚。如果它只是G1or G2,我认为这会更容易,但两者一起出现重复计数的问题 - bys 可能包括G1计数和G2计数中的观察。

我想问这个问题的另一种方法是,是否有一种方法可以像R's applyfamily 一样在每个观察/行上执行函数,或者我是否需要像我在这里那样使用笨拙的循环方法。

标签: rfunctiongroupingstatalapply

解决方案


在这种情况下,如果你有一个大数据集,使用preserveandrestore会使它变慢。您还生成了几个可能不需要的中间变量。如果我正确理解您的问题,您的代码可以大大简化。我正在使用Stata 14:

local N = _N
forvalues i = 1/`N' {
    tempvar tempv 
    gen `tempv' = (G1 != G1[`i'] & G2 ! = G2[`i'])
    sum v if `tempv' == 1, 
    replace computed = r(sum)/r(N) in `i'
}

编辑新泽西州:

这反过来可以简化(并加快)

forvalues i = 1/`=_N' { 
    summarize  v if G1 != G1[`i'] & G2 != G2[`i'], meanonly 
    replace computed = r(mean) in `i' 
}

请注意,上面的代码为每个观察创建一个新的临时变量,但您不需要其中任何一个。此外,为您提供平均值的选项meanonlysummarize它也为您提供其他结果,但无需计算r(sum)/r(N)何时summarize已经完成。

随意将此编辑与主要问题合并。我认为发布不同的答案没有意义,除非并且直到我能找到一种避免观察循环的方法。


推荐阅读