我试图编写健壮的代码来为宏变量赋值。我希望宏变量的名称取决于来自变量'子组'的值。因此子组可以等于1,2或45等,因此具有宏变量名trta_1,trta_2,trt_45等。
我遇到困难的地方是调用宏变量名。所以不要叫例如& trta_1我想调用& trta_%SCAN(& subgroups,& k),它在第一次迭代时解析为trta_1。我在宏变量名称中使用了%SCAN函数,这会抛出警告“警告:表示符号引用TRTA_未解析。”#39;。但是,已使用分配的值创建宏变量。
如何解决警告?是否有一个我可以使用%SCAN函数运行的函数来使其工作?
data data1 ;
input subgroup trta trtb ;
datalines ;
1 30 58
2 120 450
3 670 3
run;
%LET subgroups = 1 2 3 ;
%PUT &subgroups;
%MACRO test;
%DO k=1 %TO 3;
DATA test_&k;
SET data1;
WHERE subgroup = %SCAN(&subgroups, &k);
CALL SYMPUTX("TRTA_%SCAN(&subgroups, &k)", trta, 'G');
CALL SYMPUTX("TRTB_%SCAN(&subgroups, &k)", trtb, 'G');
RUN;
%PUT "&TRTA_%SCAN(&subgroups, &k)" "&TRTB_%SCAN(&subgroups, &k)";
%END;
%MEND test;
%test;
答案 0 :(得分:1)
使用您提供的以下结构将获得您正在寻找的结果。
data data1;
input subgroup trta trtb;
datalines;
1 30 58
2 120 450
3 670 3
;
run;
%LET SUBGROUPS = 1 2 3;
%PUT &SUBGROUPS;
%MACRO TEST;
%DO K=1 %TO 3;
%LET X = %SCAN(&SUBGROUPS, &K) ;
data test_&k;
set data1;
where subgroup = &X ;
call symputx(cats("TRTA_",&X), trta, 'g');
call symputx(cats("TRTB_",&X), trtb, 'g');
run;
%PUT "&&TRTA_&X" "&&TRTB_&X";
%END;
%MEND TEST;
%TEST;
但是,我不确定这种方法是否特别强大。如果您的子组列表发生更改,则需要手动更改“K”循环,您可以通过动态计算子组列表中的“元素”来确定循环的上限。
如果你想调用稍后在代码中创建的宏变量,你可以使用类似的方法。
data data2;
input subgroup value;
datalines;
1 20
2 25
3 15
45 30
;
run ;
%MACRO TEST2;
%DO K=1 %TO 3;
%LET X = %SCAN(&SUBGROUPS, &K) ;
data data2 ;
set data2 ;
if subgroup = &X then percent = value/&&TRTB_&X ;
format percent percent9.2 ;
run ;
%END;
%MEND TEST2;
%TEST2 ;
实际上,你是在循环的每次迭代中重写data2。
答案 1 :(得分:0)
这应该涵盖您的要求。您可以在没有宏的情况下加载和卸载宏变量数组。我已经提供了另一种方法来卸载宏变量数组和宏来进行比较。
将值加载到宏变量中,包括宏变量名称中的子组编号,例如TRTA_45。
data data1;
input subgroup trta trtb;
call symput ('TRTA_'||compress (subgroup), trta);
call symput ('TRTB_'||compress (subgroup), trtb);
datalines;
1 30 58
2 120 450
3 670 3
45 999 111
;
run;
无需加载宏或引用宏变量。
%put TRTA_45: &TRTA_45.;
%let Subgroup_num = 45;
%put TRTB__&subgroup_num.: &&TRTB_&subgroup_num.;
如果需要遍历宏变量,则可以使用Proc SQL生成子组列表。
proc sql noprint;
select subgroup
, count (*)
into :subgroups separated by ' '
, :No_Subgroups
from data1
;
quit;
%put Subgroups: &subgroups.;
%put No_Subgroups: &No_Subgroups.;
使用宏循环遍历宏变量数组并填充表。
%macro subgroups;
data subgroup_data_macro;
%do i = 1 %to &no_subgroups.;
%PUT TRTA_%SCAN(&subgroups, &i ): %cmpres(&TRTA_%SCAN(&subgroups, &i ));
%PUT TRTB_%SCAN(&subgroups, &i ): %cmpres(&TRTB_%SCAN(&subgroups, &i ));
subgroup = %SCAN(&subgroups, &i );
TRTA = %cmpres(&TRTA_%SCAN(&subgroups, &i ));
TRTB = %cmpres(&TRTB_%SCAN(&subgroups, &i ));
output;
%end;
run;
%mend subgroups;
%subgroups;
或者使用数据步骤(在宏外部)循环遍历宏变量数组并填充表格。
data subgroup_data_sans_macro;
do i = 1 to &no_subgroups.;
subgroup = SCAN("&subgroups", i );
TRTA = input (symget (compress ('TRTA_'||subgroup)),20.);
TRTB = input (symget (compress ('TRTB_'||subgroup)),20.);
output;
end;
run;
确保两种方法(在宏内和不在内)产生相同的结果。
proc compare
base = subgroup_data_sans_macro
compare = subgroup_data_macro
;
run;