我有一个包含多个子组(变量economist
)和日期(变量temps99
)的数据集。
我想运行一个不接受tabsplit
或bysort
前缀的by
命令。所以我创建了一个宏来将tabsplit
命令应用于我的数据中的每个子组。
例如:
levelsof economist, local(liste)
foreach gars of local liste {
display "`gars'"
tabsplit SubjectCategory if economist=="`gars'", p(;) sort
return list
replace nbcateco = r(r) if economist == "`gars'"
}
对于每个子组,Stata运行tabsplit
命令,并使用变量nbcateco
来存储计数结果。
我在约会时做了同样的事情,所以随着时间的推移我可以进行r(r)
的演变:
levelsof temps99, local(liste23)
foreach time of local liste23 {
display "`time'"
tabsplit SubjectCategory if temps99 == "`time'", p(;) sort
return list
replace nbcattime = r(r) if temps99 == "`time'"
}
现在我希望按日期economist
在每个子组temps99
上执行此操作。我尝试了多种组合,但我对宏不是很好(但是?)。
我想要的是能够随着时间的推移为我的每个小组提供r(r)
。
答案 0 :(得分:2)
这是一个解决方案,展示了如何计算每个分组中不同发布类别的数量。这使用runby
(来自SSC)。 runby
遍历每个by-group,每次用当前副组的数据替换内存中的数据。对于每个副组,执行用户程序中包含的命令。当用户的程序终止时留在存储器中的任何内容被认为是结果并累积。处理完所有组后,这些结果将替换内存中的数据。
我使用了verbose
选项,因为我想使用漂亮的格式为每个分组显示结果。通过拆分每个列表,转换为长布局,并将每个不同值减少到一个观察值来完成不同类别列表的推导。 distinct_categories
程序生成一个变量,其中包含按组的不同类别的最终计数。
* create a demontration dataset
* ------------------------------------------------------------------------------
clear all
set seed 12345
* Example generated by -dataex-. To install: ssc install dataex
clear
input str19 economist
"Carmen M. Reinhart"
"Janet Currie"
"Asli Demirguc-Kunt"
"Esther Duflo"
"Marianne Bertrand"
"Claudia Goldin"
"Bronwyn Hughes Hall"
"Serena Ng"
"Anne Case"
"Valerie Ann Ramey"
end
expand 20
bysort economist: gen temps99 = 1998 + _n
gen pubs = runiformint(1,10)
expand pubs
sort economist temps99
gen pubid = _n
local nep NEP-AGR NEP-CBA NEP-COM NEP-DEV NEP-DGE NEP-ECM NEP-EEC NEP-ENE ///
NEP-ENV NEP-HIS NEP-INO NEP-INT NEP-LAB NEP-MAC NEP-MIC NEP-MON ///
NEP-PBE NEP-TRA NEP-URE
gen SubjectCategory = ""
forvalues i=1/19 {
replace SubjectCategory = SubjectCategory + " " + word("`nep'",`i') ///
if runiform() < .1
}
replace SubjectCategory = subinstr(trim(SubjectCategory)," ",";",.)
leftalign // from SSC
* ------------------------------------------------------------------------------
program distinct_categories
dis _n _n _dup(80) "-"
dis as txt "fille = " as res economist[1] as txt _col(68) " temps = " as res temps99[1]
// if there are no subjects for the group, exit now to avoid a no obs error
qui count if !mi(trim(SubjectCategory))
if r(N) == 0 exit
// split categories, reshape to a long layout, and reduce to unique values
preserve
keep pubid SubjectCategory
quietly {
split SubjectCategory, parse(;) gen(cat)
reshape long cat, i(pubid)
bysort cat: keep if _n == 1
drop if mi(cat)
}
// show results and generate the wanted variable
list cat
local distinct = _N
dis _n as txt "distinct = " as res `distinct'
restore
gen wanted = `distinct'
end
runby distinct_categories, by(economist temps99) verbose
答案 1 :(得分:1)
我认为这是XY问题的一个例子。见http://xyproblem.info/
tabsplit
是来自SSC的包tab_chi
中的命令。就像我写的那样,我对它没有负面的感觉,但这里似乎没有必要。
您想要计算字符串变量中的类别:分号是您的分隔符。所以计算分号并添加1.
local SC SubjectCategory
gen NCategory = 1 + length(`SC') - length(subinstr(`SC', ";", "", .))
然后(例如)table
或tabstat
会让您进一步探索感兴趣的群组。
要查看计数概念,请考虑3个类别,包含2个分号。
. display length("frog;toad;newt")
14
. display length(subinstr("frog;toad;newt", ";", "", .))
12
如果我们用空字符串替换每个分号,则长度的变化是删除的分号数。请注意,我们不必更改变量来执行此操作。然后添加1.另请参阅this paper。
那就是说,扩展你的方法的方法可能是
egen class = group(economist temps99), label
su class, meanonly
local nclass = r(N)
gen result = .
forval i = 1/`nclass' {
di "`: label (class) `i''"
tabsplit SubjectCategory if class == `i', p(;) sort
return list
replace result = r(r) if class == `i'
}
使用statsby
会更好。另见this FAQ。