【问题标题】:How can I use %SCAN within a macro variable name?如何在宏变量名称中使用 %SCAN?
【发布时间】:2014-09-10 12:26:54
【问题描述】:

我正在尝试编写健壮的代码来为宏变量赋值。我希望宏变量的名称取决于来自变量“子组”的值。因此子组可以等于 1、2 或 45 等,因此具有宏变量名称 trta_1、trta_2、trt_45 等。

我遇到困难的地方是调用宏变量名。所以不要打电话给例如&trta_1 我想调用 &trta_%SCAN(&subgroups, &k),它在第一次迭代时解析为 trta_1。我在宏变量名称中使用了 %SCAN 函数,该函数抛出警告“警告:明显的符号引用 TRTA_ 未解析。”。但是,宏变量已创建并分配了值。

如何解决该警告?有没有我可以使用 %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;

【问题讨论】:

  • 您在宏中使用了&subgroups,但在外部使用了&subtest
  • @dennis suter 啊,是的,我正在测试它,忘记改回来了,谢谢!现在更新了。

标签: sas sas-macro


【解决方案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。

【讨论】:

  • 那行得通。但是,我应该说的是我想在该宏之外使用宏变量,所以我希望能够在其他地方的代码中调用 &trta_1 或 &trta_2 或 &trtb_3 或 &trtb_45 等。在后面的代码中我说,例如,如果 subgroup=45 then percent=value/&trtb_45,只有我使用 %scan(&subgroups, &k),所以我没有明确说明 trtb_45,因为它可能在另一个 re -运行 trtb_309。
  • 编辑了我的答案。只是想强调一下,几乎可以肯定有更好的方法来解决您的问题,但是如果不确切知道您在做什么,就很难提供进一步的建议。
  • 是的,我想你就在那里。如果稍后在我计算百分比的代码中使用 %let 语句创建宏变量,我可以做到这一点。它在我的宏变量名称中使用 %SCAN 函数。也许稍后我可以使用 %scan 函数弄清楚如何做到这一点,但现在我对你的建议很满意 - 谢谢!
  • 同意评论“几乎可以肯定有更好的方法来解决您的问题”。这是宏语言是错误答案的一个很好的例子。
【解决方案2】:

这应该满足您的要求。您可以在没有宏的情况下加载和卸载宏变量数组。我提供了另一种卸载宏变量数组的方法,其中包含用于比较的宏。

将值加载到宏变量中,包括宏变量名称中的子组编号,例如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;    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-08
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    相关资源
    最近更新 更多