我正在尝试动态创建保留列表。说:
%MACRO TEST(A=,B=,OUT_VAR=,KEEP_VAR=);
&OUT_VAR=MAX(&A,&B);
%IF &KEEP_VAR = 'Y' %THEN VAR_LIST=%SYSFUNC(CATS(VAR_LIST,&OUT_VAR));
%PUT VAR_LIST;
%MEND;
DATA ABC (keep = VAR_LIST);
LENGTH VAR_LIST $100.;
RETAIN VAR_LIST '';
%TEST(A=1,B=3,OUT_VAR=FIRS,KEEP_VAR='Y');
%TEST(A=2,B=4,OUT_VAR=SEC,KEEP_VAR='Y');
%TEST(A=3,B=5,OUT_VAR=THIR,KEEP_VAR='N');
RUN;
我有一个datastep,我在其中创建由宏代码计算的几个变量。 我想创建这些输出变量的动态列表,然后在keep语句中使用它。 上面的代码似乎不起作用,有人可以建议我在这里缺少什么。
答案 0 :(得分:0)
正在运行的数据步骤是已编译的源代码。您正在尝试在运行时更改源 - 这不会发生。这是在宏代码和生成的代码之间混合范围和上下文的症状。
但是,TEST
宏正在生成源,因此可以
KEEP
源代码语句。KEEP
调用生成一个额外的TEST
语句通常,仅宏参数值已经是'字符串',并且不需要引用。
%MACRO TEST(A=,B=,OUT_VAR=,KEEP_VAR=);
&OUT_VAR=MAX(&A,&B);/* generates data step source code*/
%IF &KEEP_VAR = 'Y' %THEN
%LET VAR_LIST=&VARLIST &OUT_VAR;
%MEND;
* must occur before sequence of TEST invocations;
%global VARLIST; * globals generally want to be avoided, next version avoids it;
%let VARLIST =;
DATA ABC;
%TEST(A=1,B=3,OUT_VAR=FIRS,KEEP_VAR='Y');
%TEST(A=2,B=4,OUT_VAR=SEC,KEEP_VAR='Y');
%TEST(A=3,B=5,OUT_VAR=THIR,KEEP_VAR='N');
KEEP &VARLIST;
RUN;
%symdel VARLIST;
我希望这是一个学习练习 - 上面的编码模式有一个宏生成代码,就像两个正常的非宏数据步骤语句一样。太多的宏观化可能会混淆。
此外,输出ABC
可能与您的预期不符。将有一个行,A = 3,B = 5,FIRS = 4,SEC = 6且无THIR = 8。所以你也有一些混合的行和列数据概念。
以下是TEST
生成KEEP
%MACRO TEST(A=,B=,OUT_VAR=,KEEP_VAR=);
&OUT_VAR=MAX(&A,&B);/* generates data step source code*/
%IF %upcase(&KEEP_VAR) = Y %THEN %STR(KEEP &OUT_VAR;);
%MEND;
DATA ABC;
%TEST(A=1,B=3,OUT_VAR=FIRS,KEEP_VAR=Y);
%TEST(A=2,B=4,OUT_VAR=SEC,KEEP_VAR=Y);
%TEST(A=3,B=5,OUT_VAR=THIR,KEEP_VAR=N);
RUN;
宏代码仍然需要依赖调用者来指定正确的KEEP_VAR
参数Y或不是Y.
另一种方法是将Y / N KEEP概念推入两个参数,使用一个参数而不是另一个参数来区分KEEP。
%MACRO TEST(A=,B=,KEEP_VAR=,TEMP_VAR=);
%IF %length (&KEEP_VAR) %then %do;
&KEEP_VAR
%end;
%else %do;
&TEMP_VAR
%end;
MAX(&A,&B);
%IF %length (&KEEP_VAR) %then %do;
KEEP &KEEP_VAR;
%end;
%MEND;
DATA ABC;
%TEST(A=1,B=3,KEEP_VAR=FIRS);
%TEST(A=2,B=4,KEEP_VAR=SEC);
%TEST(A=3,B=5,TEMP_VAR=THIR);
RUN;
对我来说,一个广泛使用的宏应该具有明确的调用。宏实现的黑盒子可以努力保持干净和高效,但不一定如此。
答案 1 :(得分:0)
目前尚不清楚您要做什么,但如果需要,您可以使用多个KEEP
语句。
data want ;
x=1;
keep x;
y=2;
z=3;
keep z;
run;
虽然对于您的应用程序,您可能希望生成DROP
语句。
%MACRO TEST(A=,B=,OUT_VAR=,KEEP_VAR=Y);
&OUT_VAR=MAX(&A,&B);
%IF (&KEEP_VAR ^= Y) %THEN %DO;
drop &out_var ;
%end;
%MEND;
DATA ABC ;
%TEST(A=1,B=3,OUT_VAR=FIRST)
%TEST(A=2,B=4,OUT_VAR=SECOND)
%TEST(A=3,B=5,OUT_VAR=THIRD,KEEP_VAR=N)
RUN;