我正在寻找一种在数据步骤中使用普通变量值作为宏变量的方法。
例如,我有宏变量& statesList_Syphilis = AAA
和另一个宏变量& statesList_Giardia = BBB
在数据步骤中,我有一个变量 Germ ,它包含2行:“Syphilis”和“Giardia”。
在我的数据步骤中,当Germ =“Syphilis”时,我需要在迭代第一行时找到 AAA 当迭代第二行时, BBB ,当Germ =“Giardia”时
尝试看起来像这样
%let statesList_Syphilis = AAA;
%let statesList_Giardia = BBB;
data test;
set mytablewithgerms; * contains variable Germ ;
* use germ and store it in &germ macro variable ;
* something like %let germ = germ; or call symput ('germ',germ);
* I want to be able to do this;
xxx = "&&statesList_&germ"; * would give xxx = "AAA" or xxx = "BBB";
* or this;
&&statesList_&germ = "test"; * would give AAA = "test" or BBB = "test";
run;
我不认为这是可能的,但我想我会要求确定。
谢谢!
编辑(评论中的问题,我正在为我的具体问题添加上下文,但我觉得这会使事情变得更复杂):
这是为了简化问题。
实际上, AAA 和 BBB 是很长的单词列表 喜欢
"asymptomatic_1 fulminant_1 chronic_1 chronic_1 fatalFulminant_1 hepatocellular_1 compensated_1 hepatocellular_2 decompensated_1 fatalHepatocellular_1 fatalHepatocellular_2 fatalDecompensated_1"
我不想将这个长字符串存储在变量中,我想在do循环中迭代这个字符串的每个单词,例如:
%do k=1 %to %sysfunc(countw(&&statesList_&germ));
%let state = %scan(&&statesList_&germ, &k);
* some other code here ;
%end;
EDIT2:
这是对我的问题的更完整的看法:
%macro dummy();
data DALY1;
* set lengths ;
length Germ $10 Category1 $50 Category2 $50 AgeGroupDALY $10 Gender $2 value 8 stateList$999;
* make link to hash table ;
if _n_=1 then do;
*modelvalues ----------------;
declare hash h1(dataset:'modelData');
h1.definekey ('Germ', 'Category1', 'Category2', 'AgeGroupDALY', 'Gender') ;
h1.definedata('Value');
h1.definedone();
call missing(Germ, Value, Category1, Category2);
* e.g.
rc=h1.find(KEY:Germ, KEY:"ssssssssss", KEY:"ppppppppppp", KEY:AgeGroupDALY, KEY:Gender);
*states ---------------------;
declare hash h2(dataset:'states');
h2.definekey ('Germ') ;
h2.definedata('stateList');
h2.definedone();
end;
set DALY_agregate;
put "°°°°° _n_=" _n_;
DALY=0; * addition of terms ;
rc2=h2.find(KEY:Germ); * this creates the variable statesList;
put "statesList =" statesList;
* here i need statesList as a macro variable,;
%do k=1 %to %sysfunc(countw(&statesList)); *e.g. acute_1 asymptomatic_1 ...;
%let state = %scan(&statesList, &k);
put "=== &k &state";
&state = 1; * multiplication of terms ;
* more code here;
%end;
run;
%mend dummy;
%dummy;
EDIT3:
输入数据集如下所示
Germ AgeGroup1 AgeGroup2 Gender Cases Year
V_HBV 15-19 15-19 M 12 2015
V_HBV 15-19 15-19 M 8 2016
V_HBV 20-24 20-24 F 37 2011
V_HBV 20-24 20-24 F 46 2012
V_HBV 20-24 20-24 F 66 2013
输出数据集将添加由宏变量定义的字符串中包含的变量,该变量取决于Germ。
例如对于V_HBV,它将创建以下变量:asymptomatic_1 fulminant_1 chronic_1 chronic_1 fatalFulminant_1 hepatocellular_1 compensated_1 hepatocellular_2 decompensated_1 fatalHepatocellular_1 fatalHepatocellular_2 fatalDecompensated_1
答案 0 :(得分:0)
我没有关注大局,但是你问题的前一次迭代之一有一些代码(伪代码),它说明了宏语言如何工作的可能混淆。考虑这一步:
data _null_;
germ="Syph";
call symput('germ',germ);
%let Germ=%sysfunc(cats(germ));
put "germ = &germ";
run;
%put &germ;
执行新SAS会话中的日志显示:
1 data _null_;
2 germ="Syph";
3 call symput('germ',germ);
4 %let Germ=%sysfunc(cats(germ));
5 put "germ = &germ";
6 run;
germ = germ
7 %put &germ;
Syph
现在让我们谈谈发生了什么。我将使用日志中的行号。
第2行将文本字符串Syph分配给数据步变量germ。没什么特别的。
第3行创建一个名为Germ的宏变量,并分配datastep变量germ的值。所以它赋予它Syph的价值。执行数据步骤时执行此CALL SYMPUT语句。
第4行是一个宏%let语句。它创建一个名为Germ的宏变量,并为其赋值germ。因为这是一个宏语句,所以它在任何DATA STEP代码执行之前执行。它不知道数据步骤变量。第4行相当于%let Germ =胚芽。对于宏语言,右侧只是一个四字符串的细菌。它不是数据步变量的名称。 %syfunc(cats())什么都不做,因为没有要连接的项目列表。
第5行是数据步骤PUT语句。在编译数据步骤时解析宏参考和细菌。此时宏变量germ解析为Germ,因为%LET语句已执行(CALL SYMPUT语句尚未执行)。
第7行是%PUT语句,它在DATA NULL 步骤完成后执行(并且在CALL SYMPUT将值Syph写入宏变量Germ之后)。
作为一般原则,难以(并且不常见)有一个数据步骤,您使用数据创建宏变量(例如通过调用symput)并在同一步骤中使用该宏变量(即引用宏变量)。在执行任何数据步骤代码之前解析宏引用。
通常,如果您的数据已经在数据集中,您可以通过数据步骤语句(DO循环而不是%DO循环等)获得所需的数据。或者,您可以使用一个DATA步骤生成宏变量,第二个DATA步骤可以引用它们。
希望有所帮助。