【问题标题】:Creating variables from macro variables with increasing index in SAS在 SAS 中从具有递增索引的宏变量创建变量
【发布时间】:2021-08-30 17:08:30
【问题描述】:

我正在尝试从 SAS 宏中索引增加的宏变量创建变量,但我得到变量 aa_index 的缺失值,并且我得到 bb_index 的 0 值,这不应该是这种情况。请帮助我如何调整我的宏以正常工作。我的 SAS 宏如下所示;

    %macro cashflow_macro(index=,aa_1=,aa_2=,aa_3=,aa_4=,);
    /*create bb fields*/
    %put bb_1 = &aa_&index - &aa_(&index+1);
    %put bb_2 = &aa_(&index+1) - &aa_(&index+2);
    %put bb_3 = &aa_(&index+2) - &aa_(&index+3);

    /*create cc fields*/
    cc_1 = max(bb_1,0);
    cc_2 = max(bb_2,0);
    cc_3 = max(bb_3,0);
%mend;

data ccc;
%cashflow_macro(index=1,aa_1=400,aa_2=300,aa_3=250,aa_4=270);
run;

【问题讨论】:

  • 请提供一个示例,说明您如何使用指定的参数调用宏,以及我假设的数据步骤?
  • 对于初学者,您的bb_## 引用应该以 & 开头,表示它们是宏变量。您还需要%eval%sysevalf 使您的增量(&index+8) 正常工作,我怀疑您需要删除括号()。诸如 cc_24 之类的赋值在开放代码中没有意义,因此您的代码存在许多问题。在不知道您要达到的目标的情况下,我不确定从哪里开始修复。并且%PUT 显示不是它创建的变量。我认为您需要 %LET。
  • 只使用 4 个 aa_ 变量创建一个简化版本,并向我们展示您希望从宏调用中生成的 SAS 代码。现在这有很多问题,但由于这些问题,它应该是什么还不清楚。
  • 这是一个简化的例子,我创建宏然后调用它; %macro cashflow_macro(index=,aa_1=,aa_2=,aa_3=,aa_4=,); /*创建bb字段*/ %put bb_1 = &aa_&index - &aa_(&index+1); %put bb_2 = &aa_(&index+1) - &aa_(&index+2); %put bb_3 = &aa_(&index+2) - &aa_(&index+3); /*创建 cc 字段*/ cc_1 = max(bb_1,0); cc_2 = 最大值(bb_2,0); cc_3 = max(bb_3,0); %修补;数据cc; %cashflow_macro(index=1,aa_1=400,aa_2=300,aa_3=250,aa_4=270);运行;
  • 请显示您希望通过此宏调用生成的 SAS 代码(没有宏变量引用):%cashflow_macro(index=1,aa_1=400,aa_2=300,aa_3=250,aa_4=270);

标签: sas sas-macro


【解决方案1】:

主要将其从宏中取出并放入效率更高的数组中。

%macro cashflow_macro(index=,aa_1=,aa_2=,aa_3=,aa_4=,);

*create variable with index - 1 for other variables;
%let index1 = %eval(&index - 1);

 *declare arrays;
 array _aa (*) aa_1-aa_&index (
 %do i=1 %to &index;
     &&&aa_&i.
 %end;
    );
    
array _bb(*) bb_1 - bb_&index1;
array _cc(*) cc_1 - cc_&index1;

*calculations;
do i=1 to &index1;
_bb(i) = _aa(i) - _aa(i+1);
_cc(i) = max(_bb(i), 0);
end;




%mend;

data ccc;
 %cashflow_macro(index=4,aa_1=400,aa_2=300,aa_3=250,aa_4=270);
run;

还有一个可能更简化的版本:

%macro cashflow_macro_revised(series=);
   
    *create variable with index - 1 for other variables;
    %let index = %sysfunc(countw(&series));
    %let index1 = %eval(&index - 1);
    
     *declare arrays;
     array _aa (*) aa_1-aa_&index (&series);
        
    array _bb(*) bb_1 - bb_&index1;
    array _cc(*) cc_1 - cc_&index1;
    
    *calculations;
    do i=1 to &index1;
    _bb(i) = _aa(i) - _aa(i+1);
    _cc(i) = max(_bb(i), 0);
    end;




%mend;

data ccc;
     %cashflow_macro_revised(series=400 300 250 270);
run;

如果您真的想坚持使用宏,这将起作用,但会产生一些警告。我没有时间调试除此之外,但它似乎工作。

%macro cashflow_macro(index=4,aa_1=,aa_2=,aa_3=,aa_4=,);
   
    *create variable with index - 1 for other variables;
    %let index1 = %eval(&index - 1);
    

     %do i=1 %to &index1;
     
        %let bb_&i =  &&&aa_&i. - &&&aa_%eval(&i+1);
        bb_&i = &&&bb_&i.;
        cc_&i = max(&&&bb_&i, 0);
     %end;




%mend;



data ccc1;
%cashflow_macro(index=4,aa_1=400,aa_2=300,aa_3=250,aa_4=270);
run;

【讨论】:

  • 为什么需要创建INDEX1? do i=1 to &index - 1;
  • 如果它在多个地方使用,我喜欢只计算一次。其他数组的索引也是 index-1。在最后一个示例中可能不需要它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
相关资源
最近更新 更多