是否可以在 Stata 的函数内调用全局宏?
Is it possible to invoke a global macro inside a function in Stata?
我有一组变量,我已将其列表保存在全局宏中,以便我可以在函数中使用它们
global inlist_cond "amz2002ras_clss, amz2003ras_clss, amz2004ras_clss, amz2005ras_clss, amz2006ras_clss, amz2007ras_clss, amz2008ras_clss, amz2009ras_clss, amz2010ras_clss, amz2011ras_clss"
之所以将它们保存在宏中,是因为列表会循环,内容会根据年份变化。
我需要做的是生成一个虚拟变量,以便 water_dummy == 1 如果宏列表中的任何变量具有 WATER 分类。在 Stata 中,我需要写
gen water_dummy = inlist("WATER", "$inlist_cond")
,理想情况下应转换为
gen water_dummy = inlist("WATER", amz2002ras_clss, amz2003ras_clss, amz2004ras_clss, amz2005ras_clss, amz2006ras_clss, amz2007ras_clss, amz2008ras_clss, amz2009ras_clss, amz2010ras_clss, amz2011ras_clss)
但这没有用——代码执行没有任何错误,但虚拟变量只包含 0。我知道可以在 Stata 的函数内部调用宏,但是当宏包含整个条件列表时我从未尝试过。有什么想法吗?
如果您的数据结构类似于以下示例,您可以尝试 egen
函数 incss
,来自 egenmore
(ssc install egenmore
):
clear
set more off
input ///
str15(amz2009 amz2010)
"water" "juice"
"milk" "water"
"lemonade" "wine"
"water & beer" "tea"
end
list
egen watindic = incss(amz*), sub(water)
list
注意它搜索 substrings(查看最后一个示例观察的结果)。
一个循环实现不同结果的解决方案是:
gen watindic2 = 0
forvalues i = 2009/2010 {
replace watindic2 = 1 if amz`i' == "water"
}
list
另一个解决方案涉及 reshape
,但我会保留它。
指定了一个文字字符串,generate
语句中的双引号坚持这样做,然后您将文本与文本进行比较,而根本不是与数据进行比较。
. clear
. set obs 1
number of observations (_N) was 0, now 1
. gen a = "water"
. gen b = "wine"
. gen c = "beer"
. global myvars "a,b,c"
. gen found1 = inlist("water", "$myvars")
. gen found2 = inlist("water", $myvars)
. list
+---------------------------------------+
| a b c found1 found2 |
|---------------------------------------|
1. | water wine beer 0 1 |
+---------------------------------------+
第一次比较相当于
. di inlist("water", "a,b,c")
0
找不到匹配项,因为 "water"
与(单个!)其他参数不匹配。
在函数或命令调用中肯定允许使用宏引用:由于在检查语法之前每个宏名称都被其内容替换,因此函数或命令甚至不知道曾经使用过宏引用。
正如@Aspen Chen 简明扼要地指出的那样,只要 inlist()
语法仍然合法,省略双引号就可以满足您的需求。
我有一组变量,我已将其列表保存在全局宏中,以便我可以在函数中使用它们
global inlist_cond "amz2002ras_clss, amz2003ras_clss, amz2004ras_clss, amz2005ras_clss, amz2006ras_clss, amz2007ras_clss, amz2008ras_clss, amz2009ras_clss, amz2010ras_clss, amz2011ras_clss"
之所以将它们保存在宏中,是因为列表会循环,内容会根据年份变化。
我需要做的是生成一个虚拟变量,以便 water_dummy == 1 如果宏列表中的任何变量具有 WATER 分类。在 Stata 中,我需要写
gen water_dummy = inlist("WATER", "$inlist_cond")
,理想情况下应转换为
gen water_dummy = inlist("WATER", amz2002ras_clss, amz2003ras_clss, amz2004ras_clss, amz2005ras_clss, amz2006ras_clss, amz2007ras_clss, amz2008ras_clss, amz2009ras_clss, amz2010ras_clss, amz2011ras_clss)
但这没有用——代码执行没有任何错误,但虚拟变量只包含 0。我知道可以在 Stata 的函数内部调用宏,但是当宏包含整个条件列表时我从未尝试过。有什么想法吗?
如果您的数据结构类似于以下示例,您可以尝试 egen
函数 incss
,来自 egenmore
(ssc install egenmore
):
clear
set more off
input ///
str15(amz2009 amz2010)
"water" "juice"
"milk" "water"
"lemonade" "wine"
"water & beer" "tea"
end
list
egen watindic = incss(amz*), sub(water)
list
注意它搜索 substrings(查看最后一个示例观察的结果)。
一个循环实现不同结果的解决方案是:
gen watindic2 = 0
forvalues i = 2009/2010 {
replace watindic2 = 1 if amz`i' == "water"
}
list
另一个解决方案涉及 reshape
,但我会保留它。
指定了一个文字字符串,generate
语句中的双引号坚持这样做,然后您将文本与文本进行比较,而根本不是与数据进行比较。
. clear
. set obs 1
number of observations (_N) was 0, now 1
. gen a = "water"
. gen b = "wine"
. gen c = "beer"
. global myvars "a,b,c"
. gen found1 = inlist("water", "$myvars")
. gen found2 = inlist("water", $myvars)
. list
+---------------------------------------+
| a b c found1 found2 |
|---------------------------------------|
1. | water wine beer 0 1 |
+---------------------------------------+
第一次比较相当于
. di inlist("water", "a,b,c")
0
找不到匹配项,因为 "water"
与(单个!)其他参数不匹配。
在函数或命令调用中肯定允许使用宏引用:由于在检查语法之前每个宏名称都被其内容替换,因此函数或命令甚至不知道曾经使用过宏引用。
正如@Aspen Chen 简明扼要地指出的那样,只要 inlist()
语法仍然合法,省略双引号就可以满足您的需求。