Stata 的暂元(Macro)在 Stata 编程中用途广泛,尤其在循环语句中。即使不编程,也可使用暂元提高 Stata 的工作效率。暂元又分为 “局部暂元”(local macro)与 “全局暂元”(global macro)两种。究竟什么是暂元?其实很简单……
删繁就简
Stata 的暂元(Macro)其实就是以一个简单的单词来指代一串复杂的字符或表达式。比如,想在 Stata 中显示字母 “A B C”,可输入
. display "A B C"
A B C
其中,“display” 中的下划线表示可将 “display” 缩写为 “di”;而 "A B C" 中的双引号表示原封不动地显示双引号中的内容。
下面,我们定义一个“局部暂元”(local macro)来指代 “A B C”:
. local letter A B C
此命令 local 定义了一个名称(name)为 “letter” 的局部暂元,而其取值(value)为 “A B C”。如此定义之后,即可用 “letter” 来指代 “A B C”。当然,在以后调用暂元时,需要告诉 Stata 这是一个局部暂元,即以单引号来表示,比如,`letter'。
. di "`letter'"
A B C
注意到,左单引号(left single quote)与右单引号(right single quote)的字符并不相同。其中,左单引号 ` 在键盘左上角,位于波浪符号 ~ 的下方(共用一个键);而右单引号 ' 在键盘右边,位于双引号 " 的下方(共用一个键)。
定义局部暂元的一般句型为
local name value
其中,“name” 为局部暂元的名称,比如上文的 “letter”,而 “value” 即为此暂元所指代的内容,比如上文的 “A B C”。
由此可知,Stata的暂元其实就是一种 “别名”(alias),它包含一个名称(name)与取值(value)。当使用 `name' 来调用此局部暂元时,Stata 内置的暂元处理器(macro processor)就会自动将其替换为其相应的取值(value)。
比如,在使用上文的命令 di "`letter'" 时,Stata 看见 `letter',就将其替换为 A B C,故 Stata 其实执行的命令就是 di "A B C"。
暂元的其它格式
在上述定义暂元的句型中,也可以给 “value” 加上双引号,效果完全等价。比如,
. local letter1 "A B C"
. di "`letter1'"
A B C
另一种定义暂元的格式是,在 “name” 与 “value” 之间加上等号 “=”,表示计算 “value” 所包含的表达式。例如,
. local count 2+2
. di "`count'"
2+2
对比加上等号的效果:
. local count = 2+2
. di "`count'"
4
由此可知,加上等号 “=” 后,会把其 “value” 的计算结果赋值给此暂元。因此,除非要把某表达式的计算结果赋值给暂元,一般情况下不要在暂元名称(name)之后加上等号 “=”。
全局暂元 vs. 局部暂元
“局部暂元”(local macro)之所以称为 “局部”(local),是因为其所定义的暂元仅在定义它的 do 文件中才有效,一旦此 do 文件执行完毕,则其中所定义的局部暂元将不复存在。反之,“全局暂元”(global macro)则在 do 文件执行完毕后仍存在(即使你打开另一数据集),直至彻底退出 Stata 程序才会消失。
与局部暂元类似,定义全局暂元的一般句型为
global name value
在调用全局暂元时,只需要在其名称(name)之前加上美元符号($)即可。比如,可使用以下命令:
. global letter A B C
. di "$letter"
A B C
注意到,此全局暂元 “letter” 与上文的局部暂元 “letter” 完全同名,这是 Stata 所允许的。在 Stata 内部,将全局暂元与局部暂元视为两类不同的事物,并在局部暂元之前加下划线;比如,分别记为 “letter” (全局暂元)与 “_letter”(局部暂元)。
究竟应使用局部暂元还是全局暂元?这取决于你的需要。如果你只需要在一个 do 文件中使用此暂元,则局部暂元(local macro)就足够了。此时,如果使用全局暂元(global macro),则可能导致意想不到的后果;比如,当你运行其他 do 文件或命令时,此全局暂元依然存在,或导致混淆。
反之,如果你需要定义一个可以为多个 do 文件所共同使用的暂元,则应使用全局暂元。总之,除非有必要使用全局暂元,使用局部暂元更为安全。
显示或删除暂元
如果想显示当前所有的暂元,可使用如下命令:
. macro list
letter: A B C
S_E_depv: price
S_E_cmd: regress
S_E_vce: Robust
S_level: 95
S_ADO: BASE;SITE;.;PERSONAL;PLUS;OLDPLACE
S_StataSE: SE
S_FLAVOR: Intercooled
S_OS: Windows
S_OSDTL: 64-bit
S_MACH: PC (64-bit x86-64)
_count: 4
_letter1: A B C
_letter: A B C
其中,“letter” 是名为 letter 的全局暂元,而 “_letter” 是名为 letter 的局部暂元。以 “S_” 开头的暂元为 “系统暂元”(system macro),不会被删除。如果要删除上面的某个暂元,比如 “_letter1”,可使用命令
. macro drop _letter1
如果要删去除系统暂元之外的所有暂元,可使用命令
. macro drop _all
再次罗列所有暂元,则只剩下系统暂元了:
. macro list
S_E_depv: price
S_E_cmd: regress
S_E_vce: Robust
S_level: 95
S_ADO: BASE;SITE;.;PERSONAL;PLUS;OLDPLACE
S_StataSE: SE
S_FLAVOR: Intercooled
S_OS: Windows
S_OSDTL: 64-bit
S_MACH: PC (64-bit x86-64)
使用暂元的实例
如果定义暂元只为了表示 “A B C” 这样的简单字符,似乎没有必要。但暂元可用来指代复杂得多的字符;比如,回归方程中一串毫无规律的变量名。
作为实例,使用 Stata 自带的系统数据集 auto.dta,估计一个关于汽车的特征价格模型(hedonic pricing model),即假设汽车价格由其各项特征所决定(比如,每加仑英里数 mile per gallon、车重、车长等)。
. sysuse auto
(1978 Automobile Data)
. reg price mpg rep78 headroom trunk weight length turn displacement gear_ratio foreign, r
其中,选择项 “robust” 表示使用(异方差)稳健标准误。
下面,使用暂元(记为 xlist)表示所有解释变量,然后进行回归:
. global xlist mpg rep78 headroom trunk weight length turn displacement gear_ratio foreign
. reg price $xlist, r
回归结果与前面完全一样(从略)。显然,使用暂元 $xlist 替代原来的诸多解释变量,使得 Stata 命令更为干净。
使用暂元的好处还在于,假设你用这些解释变量进行了10个回归(比如,使用了不同的计量方法、标准误或更换被解释变量),但又突然得到新数据,想加入一个新变量。如果你没有使用暂元,则需要在 do 文件中找到这10个回归方程,然后在每个方程中手工加入此新变量。反之,如果你使用了暂元来指代解释变量,则只需重新定义暂元即可(重新定义暂元时加入新变量)。
当然,暂元的最大用途其实在于 Stata 的循环语句,这将在以后介绍循环语句时再行说明。有关暂元的更多信息,详见 “help macro” 以及相应的Stata手册。
参考文献
Baum, Christopher, 2006. An Introduction to Modern Econometrics Using Stata, Stata Press.
Baum, Christopher, 2016. An Introduction to Stata Programming, second edition, Stata Press.
(c) 2016, 陈强,山东大学经济学院 www.econometrics-stata.com
转载请注明作者与出处
长按此二维码,关注本公众号
如觉得本文赞,请转给朋友(圈)