在一个循环中,变量为数据子集所取的唯一值的数量

Number of unique values taken by a variable for a subset of the data, within a loop

我正在用 Stata 写一些代码,但是当前的迭代效率很低。我知道如果我在 python/pandas 中写这个来使事情变得更好,我会如何改变事情,但我不确定如何做 this/if 在 Stata 中是可能的。出于工作流程的原因,我需要将此代码保留为 Stata 语言。

基本问题是我有两个分类变量,catacatb。每个都可以有几千个值。我想减少 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 小时内完成具有大约 100k 个观测值的数据。

这里有问题的部分是嵌套循环,因为我正在遍历 catb 的所有可能值,即使只有大约 10 个出现(cata 平均大小是 20-30) .我想 select 只有 catb 的相关部分在嵌套循环中循环,而不是 catb 的所有可能值。在 pandas/python 我会做这样的事情:

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

说明:catb2catb的新版本,它取代了类别“1”,因为没有cata出现多个“1”。类别“2”保持不变,因为它在 cata B.

中出现了两次

如果我理解正确,你想要 drop catacatb 的组合只出现一次:

 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