问题描述
我正在用Stata写一些代码,但是当前的迭代效率很低。我知道如果我要在 python/pandas 中编写它以使事情变得更好,我将如何改变事情,但我不确定如何做到这一点/如果在 Stata 中可能。出于工作流程的原因,我需要将此代码保留为 Stata 语言。
基本问题是我有两个分类变量,cata
和 catb
。每个都可以具有数千个值。我想通过仅在同一 catb
中至少出现两个观察值时保留一个类别来减少 cata
中的类别数量。我使用 egen group()
来确保类别是数字,最大值是两个变量的类别数。
我当前的代码如下所示:
foreach var in cata catb {
qui sum `var'
local `var'_max = r(max)
}
local list
forvalues i=1/`cata_max' {
if mod(`i',10)==0 di `i' " of " `cata_max'
forvalues i=j/`catb_max' {
qui count if cata==`i' & catb==`j'
if r(N)>1 local list `list' `j'
}
}
gen mask=0
foreach i in `list' {
replace mask=1 if catb==`i'
}
replace catb=-1 if mask==0
我相信这段代码可以运行并且会起作用,但我估计在大约 16 小时内完成大约 10 万次观察的数据。
其中有问题的部分是嵌套循环,因为我正在遍历 catb
的所有可能值,即使只有大约 10ish 出现(cata
平均大小为 20-30)。我只想选择 catb
的相关部分在嵌套循环中循环,而不是 catb
的所有可能值。在熊猫/蟒蛇我会做这样的事情:
val_list=[]
for i in df['cata'].unique():
df_temp=df[df['cata']==i]
rel_vals=df_temp['catb'].unique()
for j in rel_vals:
if len(df_temp[df_temp['catb']])>1:
val_list+=[j]
虽然不是很好的代码,但说明了仅循环 catb
的相关值的想法。这应该可以将第二个循环中花费的时间减少约 300 倍,即使在查找唯一值时存在一些开销,这也会产生显着的加速。
如何在这个循环结构中只获得一个变量的唯一值?我的搜索只产生 this 之类的帖子,这是一种计算变量唯一值的迂回方法(在我的情况下,它不适用于数据子集的唯一值)。
示例:
index cata catb catb2
0 A 1 -1
1 B 2 2
2 C 1 -1
3 A 2 2
4 B 2 2
5 C 2 2
说明:catb2
是catb
的新版本,它取代了类别“1”,因为没有cata
中出现多个“1”。类别“2”保持不变,因为它在 cata
B.
解决方法
如果我理解正确,您希望 drop
和 cata
的 catb
组合只出现一次:
bysort cata catb: drop if _N == 1
,
我认为即使只循环观察 catb
的值也是一种相对低效的方法。我建议使用 duplicates
命令(为了扩展,我建议使用非常有用的 gtools 包中的 gduplicates
命令 - ssc install gtools
)。下面是一个实现示例:
clear
input index str1(cata) catb
0 "A" 1
1 "B" 2
2 "C" 1
3 "A" 2
4 "B" 2
5 "C" 2
end
// Tags unique pairs of cata and catb with N-1
// i.e. a value of 2 means that there are 3 observed pairs given cata and catb
duplicates tag cata catb,gen(observed_pairs)
// The maximum unique pairs that catb is a part of
egen catb_max = max(observed_pairs),by(catb)
// Will make new catb2 that is -1 if a catb at most 1 in each cat a
gen catb2 = catb
replace catb2 = -1 if catb_max == 0