是否可以在Stata中的函数内调用全局宏?

时间:2015-08-18 21:08:05

标签: 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分类,则water_dummy == 1。在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中的函数内部调用宏,但是当宏包含整个条件列表时我从未尝试过。有什么想法吗?

2 个答案:

答案 0 :(得分:4)

如果指定了文字字符串,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"与(single!)其他参数不匹配。

在函数或命令调用中当然允许宏引用:在检查语法之前,每个宏名称都被其内容替换,函数或命令甚至不知道曾经使用过宏引用。

正如@Aspen Chen简明地指出的那样,只要inlist()语法保持合法,省略双引号即可得到你想要的内容。

答案 1 :(得分:2)

如果您的数据结构类似于以下示例,则可以从2015-08-18 14:47:44.221 Myapp[27792:4515252] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZAUTOCREATED, t0.ZBLOCKS, t0.ZCHANGETOKEN, t0.ZCOLLECTIONID, t0.ZCREATIONDATE, t0.ZEDITDATE, t0.ZENDDATE, t0.ZFULLTEXT, t0.ZGLOBALID, t0.ZLOCATION, t0.ZLOCATIONTEXT, t0.ZSTARTDATE, t0.ZTAGS, t0.ZTHUMBNAILIMAGE, t0.ZTIMEZONE, t0.ZTITLE, t0.ZWASDELETED, t0.ZYEARMONTH, t0.ZYEARMONTHDAY FROM ZSTORY t0 WHERE t0.Z_PK IN (SELECT * FROM _Z_intarray0) ORDER BY t0.ZYEARMONTHDAY, t0.ZSTARTDATE LIMIT 100 2015-08-18 14:47:44.468 Myapp[27792:4515252] CoreData: annotation: sql connection fetch time: 0.0959s 2015-08-18 14:47:44.469 Myapp[27792:4515252] CoreData: annotation: total fetch execution time: 0.2566s for 100 rows. 2015-08-18 14:47:44.550 Myapp[27792:4515252] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZAUTOCREATED, t0.ZBLOCKS, t0.ZCHANGETOKEN, t0.ZCOLLECTIONID, t0.ZCREATIONDATE, t0.ZEDITDATE, t0.ZENDDATE, t0.ZFULLTEXT, t0.ZGLOBALID, t0.ZLOCATION, t0.ZLOCATIONTEXT, t0.ZSTARTDATE, t0.ZTAGS, t0.ZTHUMBNAILIMAGE, t0.ZTIMEZONE, t0.ZTITLE, t0.ZWASDELETED, t0.ZYEARMONTH, t0.ZYEARMONTHDAY FROM ZSTORY t0 WHERE t0.Z_PK IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ORDER BY t0.ZYEARMONTHDAY, t0.ZSTARTDATE LIMIT 100 2015-08-18 14:47:44.614 Myapp[27792:4515252] CoreData: annotation: sql connection fetch time: 0.0067s 2015-08-18 14:47:44.614 Myapp[27792:4515252] CoreData: annotation: total fetch execution time: 0.0635s for 44 rows. 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

另一个解决方案涉及gen watindic2 = 0 forvalues i = 2009/2010 { replace watindic2 = 1 if amz`i' == "water" } list ,但我会留下它。