【问题标题】:Storing values in a macro variable将值存储在宏变量中
【发布时间】:2012-10-19 18:12:47
【问题描述】:

我正在使用levelsof 命令来识别变量的唯一值并将它们粘贴到宏中。然后稍后我想使用宏中的这些值从我将加载的另一个数据集中选择记录。

我的想法大致如下:

keep if inlist(variable, "`macrovariable'")

这行得通吗?还有其他更有效的选择吗?我可以在 R 中轻松做到这一点(因为向量比宏更容易使用),但是这个项目需要 Stata。


澄清:

如果我有一个具有三个唯一值 abc 的变量,我想将它们存储在一个宏变量中,以便稍后获取另一个数据集并选择与其中一个值匹配的观察值.

通常可以使用inlist 函数手动执行此操作,但我想对其进行软编码,以便可以使用不同的值集运行程序。而且我无法让inlist 函数与宏一起使用。

【问题讨论】:

  • 你能说得更具体点吗?你试过了吗?如果是这样,它有效吗?如果没有,您遇到了什么问题?
  • 虽然常用,但“唯一”(严格的意思是,只出现一次)在这里并不是最好的术语。我推荐“不同的”。

标签: stata stata-macros


【解决方案1】:
* the source data
levelsof x, local( allx )
* make it -inlist-friendly
local allxcommas : subinstr local allx  " " ", ", all
* bring in the new data
use using blah.dta if inlist(x, `allxcommas')

【讨论】:

  • allxcommas列表过长抛出'expression too long'错误的情况有解决办法吗?
  • 第四行的local 评估点是否太长(我对其进行了编辑以使其更健壮),或者最后一行的inlist() 评估点是否太长?恐怕后者无法有意义地克服,无需将allxcommas 拆分为可管理的块,然后将append 组合在一起。
  • 非常感谢您的更新。当列表变得很长并且browse 抱怨时,这个块让我失望了。 use using 的好主意 - 会试一试。
【解决方案2】:

我怀疑您将levelsof 生成的宏与inlist 一起使用的困难在于您忘记使用separate(,) 选项。我也不相信您可以将inlist 函数与keep if 一起使用——您需要添加定义新指标的额外步骤。

在下面的示例中,我使用了 1978 年的汽车数据并创建了汽车制造商(或制造商)的变量 make_abb,它只采用了少数不同的值(道奇的“Do”等)。

然后我使用levelsof 命令生成制造商的本地宏,这些制造商的车辆型号维修记录不佳(变量rep78 是分类维修记录变量,其中 1 表示不良,5 表示良好) .选项separate(,) 将逗号添加到宏中,并允许 inlist 稍后读取它。

最后,如果我想删除那些没有维修记录不佳的制造商,我会生成一个名为“keep_me”的虚拟变量,并使用 inlist 函数填充它。

*load some data
sysuse auto 
*create some make categories by splitting the make and model string
gen make_abb=substr(make,1,2)
lab var make_abb "make abbreviation (string)"
*use levelsof with "local(macro_name)" and "separate(,)" options
levelsof make_abb if rep78<=2, separate(,) local(make_poor)
*generate a dummy using inlist and your levelsof macro from above
gen keep_me=1 if inlist(make_abb,`make_poor')
lab var keep_me "dummy of makes that had a bad repair record"
*now you can discard the rest of your data
keep if keep_me==1

【讨论】:

  • “我也不相信您可以将 inlist() 函数与 keep if 一起使用”:这绝对没有内在问题。考虑sysuse auto, clear,后跟keep if inlist(rep78, 1, 2, 3)。有什么困难?
【解决方案3】:

这似乎对我有用。

* "using" data
clear
tempfile so
set obs 10
foreach v in list a b c d {
    generate `v' = runiform()
}
save `so'

* "master" data
clear
set obs 10
foreach v in list e f g h {
    generate `v' = runiform()
}

* merge
local tokeepusing a b
merge 1:1 _n using `so', keepusing(`tokeepusing')

产量:

. list

     +------------------------------------------------------------------------------------------+
     |     list          e          f          g          h          a          b        _merge |
     |------------------------------------------------------------------------------------------|
  1. | .7767971   .5910658   .6107377   .7256517    .357592   .8953723   .0871481   matched (3) |
  2. |  .643114   .6305301   .6441092   .7770287   .5247816   .4854506   .3840067   matched (3) |
  3. | .3833295    .175099   .4530386   .5267127    .628081   .2273252   .0460549   matched (3) |
  4. | .0057233   .1090542   .1437526   .3133509    .604553   .9375801   .8091199   matched (3) |
  5. | .8772233   .6420991   .5403687   .1591801   .5742173   .8948932   .4121684   matched (3) |
     |------------------------------------------------------------------------------------------|
  6. | .6526399   .5137199    .933116   .5415702   .4313532   .8602547   .5049801   matched (3) |
  7. | .2033027   .8745837      .8609   .0087578   .9844069   .1909852   .3695011   matched (3) |
  8. | .6363281   .0064866   .6632325    .307236   .9544498   .6267227   .2908498   matched (3) |
  9. |  .366027   .4896181   .0955155   .4972361   .9161932   .7391482    .414847   matched (3) |
 10. | .8637221   .8478178   .5457179   .8971257   .9640535    .541567   .1966634   matched (3) |
     +------------------------------------------------------------------------------------------+

这是否回答了您的问题?如果没有,请评论。

【讨论】:

  • 我认为这不能解决 OP 询问的问题。
  • 我也不确定,@StasK。如果 OP 确实需要 levelsof 功能来识别另一个数据集中的观察结果,为什么不只在该变量上使用 merge 呢?
  • @StasK -- 你是对的,我正在回答一个不同的问题。但是为什么不merge呢?
  • merge 需要大量开销来比较 id 变量的值并对using 数据进行排序(master 数据将包含三个观察结果,这没什么大不了的对其进行排序)。 use using if results of levelsof 工作得更快,因为它只是一个过滤器,只需要一次通过 using 数据,而无需将排序版本保存回磁盘。所以大多数时候我更喜欢这个解决方案而不是merge。唯一需要注意的是,levelsof 在大型数据集中并不是特别快。
  • @StasK -- 我明白了。好点子。 (虽然我使用levelsof 主要用于循环,并且经常发现我的级别太多,不得不切换到egen/group() 解决方案。)感谢指点!
猜你喜欢
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多