foreach 命令宏中的多个本地

Multiple local in foreach command macro

我有一个包含多个子组(变量 economist)和日期(变量 temps99)的数据集。

我想运行一个不接受bysortby前缀的tabsplit命令。所以我创建了一个宏来将我的 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 运行s 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'"
}

现在我想按日期 temps99 在每个子组 economist 上执行此操作。我尝试了多种组合,但我对宏不是很好(还没有?)。

我想要的是能够随着时间的推移为我的每个子组拥有我的 r(r)

我认为这是 XY 问题的一个例子。参见 http://xyproblem.info/

tabsplit 是来自 SSC 的包 tab_chi 中的命令。正如我写的那样,我对此没有任何负面情绪,但在这里似乎完全没有必要。

您想计算​​字符串变量中的类别:分号是您的分隔符。所以计算分号并加 1。

local SC SubjectCategory
gen NCategory = 1 + length(`SC') - length(subinstr(`SC', ";", "", .)) 

然后(例如)tabletabstat 将让您按兴趣组进一步探索。

要查看计数思路,请考虑 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

这是一个解决方案,展示了如何计算每个按组内不同出版物类别的数量。这使用 runby(来自 SSC)。 runby 遍历每个 by-group,每次用当前 by-group 中的数据替换内存中的数据。对于每个 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