如何在宏变量名称中使用%SCAN?

时间:2014-09-10 12:26:55

标签: sas sas-macro

我试图编写健壮的代码来为宏变量赋值。我希望宏变量的名称取决于来自变量'子组'的值。因此子组可以等于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;

2 个答案:

答案 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;