让我们逐行看一下。
local var year
您定义了一个本地宏 var,其内容为 "year"。这是合法的,但您从不在此代码中引用该本地宏,因此定义毫无意义。
local j = 1996
您定义了一个本地宏 j,其内容为 "1996"。这是合法的。
foreach j of var year {
您打开一个循环并将循环索引定义为j。这意味着在循环中对本地宏 j 的任何引用都将根据您提供的参数列表进行解释。 (j 的先前定义在循环中是无关紧要的,因此对您的其余代码没有影响。)
... of var year
您在此处指定循环在变量列表上。注意这里的关键字var是varlist的缩写,和你刚刚定义的本地宏名var完全没有关系。变量列表由单个变量名称year 组成。
gen d`j' = 1 if year==`j'
该语句将被解释为循环执行的唯一一次,如
gen dyear = 1 if year==year
因为对局部宏 j 的引用被替换为它的内容,变量名 year。 year==year 对每个观察都是正确的。效果是一个新变量dyear,在每次观察中都是 1。这不是您想要的指标或虚拟变量。如果您仔细查看数据集,您会发现 year 不是 1996 年的虚拟变量。
local ++j
您正试图将本地宏 j 增加 1。但您只是将本地宏 j 设置为包含字符串 "year",这是一个变量名。但是您不能将 1 加到字符串中,因此错误消息将是 type mismatch。您没有报告该错误,这是一个惊喜。这有点微妙,因为在前面的命令中,generate 的上下文允许将对year 的引用解释为使用变量year 计算的指令,该变量自然是数字。但是local 命令都是关于字符串操作的,可能有也可能没有数字解释,而你的命令首先等同于指示 Stata 添加
"year" + 1
触发类型不匹配错误。
远离你的代码:考虑一个循环
forval y = 1996/2012 {
gen d`y' = 1 if year == `y'
}
这更接近您想要的,但更清晰地显示了您代码中的另一个错误。这将创建变量d1996 到d2012,但每个变量在指定的年份都是 1,否则会丢失,这不是你想要的。
您可以通过在循环中添加另一行来解决此问题
replace d`y' = 0 if year != `y'
但更简洁的方法是单行
gen d`y' = year == `y'
表达式
year == `y'
在 true 时被评估为 1,在 false 时被评估为 0,这就是你想要的。
所有这些都是在 [U] 或 [P] 中记录的标准技术。
然而,正如@Roberto Ferrer 指出的那样,有经验的 Stata 用户不会以这种方式定义假人,因为tabulate 提供了一个选项,可以在没有循环的情况下执行此操作。
在http://www.stata-journal.com/sjpdf.html?articlenum=pr0005 内有一个关于本地宏、foreach 和forvalues 循环的 cmets 的教程
search foreach
在 Stata 内部会指出这是您可以阅读的各种作品之一。