遍历使用 levelsof 生成的列表

Iterate over list produced with levelsof

下面的例子重现了我的问题。有一个字符串变量,它有多个值。我想创建一个全局列表并循环迭代它。但它不起作用。我试过几个版本都没有成功。这是示例代码:

webuse auto, clear
levelsof make // list of car makes
global MAKE r(levels) // save levels in global list

foreach i in $MAKE { // loop some command over saved list 
    sum if make == "`$MAKE'"  // ERROR 198, invalid 'Concord' 
}

使用“`$MAKE'”或 $MAKE 不会产生所需的输出。

知道我做错了什么吗?

通常,要使列表正常工作,它们应该保存为 A B C D [...]。在我的例子中,levelsof 生成以下类型的列表:

di $MAKE
`"AMC Concord"' `"AMC Pacer"' `"AMC Spirit"' `"Audi 5000"' `"Audi Fox"' `"BMW 320i"' [...]

所以显然不是所需要的。但不确定如何获得我需要的东西。

这是一个解决方案。请注意,我使用的是 local 而不是 global。区别仅在于范围。如果您需要引用跨 do-files 的值,请仅使用 global。您可以删除下面的 display 行。

*Sysuse reads this data from disk, it comes with all Stata installations
sysuse auto, clear

*Use levelsof, and assign the returned r(levels) using a = to the local
levelsof make
local all_makes = r(levels)

*Loop over the local like this. Note that foreach creates a local, in this
*case called this_make that stores the elements in the local one per iteration
foreach this_make of local all_makes { 
    display "`this_make'"
    sum if make == "`this_make'"
}

如果您需要全局,那么您只需将其更改为:

*Sysuse reads this data from disk, it comes with all Stata installations
sysuse auto, clear

*Use levelsof, and assign the returned r(levels) using a = to the global
levelsof make
global all_makes = r(levels)

*Loop over the global like this. Note that foreach creates a local, in this
*case called this_make that stores the elements in the global one per iteration
foreach this_make of global all_makes { 
    display "`this_make'"
    sum if make == "`this_make'"
}

有一个很好的公认答案,但还有很多可以说的。例如参见 [​​=16=].

作为其原作者,我对 levelsof 持肯定态度,但出于特定目的,要遍历变量的级别,使用 egen, group() 和循环会更简洁该变量的整数水平。有关更多信息,请参阅刚刚链接的常见问题解答。原始问题中的示例就是一个很好的例子,因为循环不同的字符串值可能很棘手,需要使用双引号 " " 并注意空格等。

根本问题没有揭示,但额外的评论是强调 by: 及其兄弟命令,如 statsby 或本质上类似的命令,如来自 SSC 的 rangestat ,实际上是循环而不循环。