【问题标题】:SAS call symput in data step数据步骤中的 SAS 调用符号
【发布时间】:2019-02-06 04:33:16
【问题描述】:

我在使用 sas 数据步骤时遇到了这个问题。我的要求是获取变量列表,例如

total_jun2018 = sum(jun2018, dep_jun2018);
total_jul2018 = sum(jul2018, dep_jul2018);

Data final4;
set final3;
by hh_no;

do i=0 to &tot_bal_mnth.;
  bal_mnth =  put(intnx('month',"&min_Completed_dt."d, i-1), monyy7.);
  call symputx('bal_mnth', bal_mnth);
  &bal_mnth._total=sum(&bal_mnth., Dep_&bal_mnth.);
  output;
end;

但我遇到了宏变量 bal_mnth 未解析的错误。同样,一旦它成功运行,但我希望输出必须按顺序打印,但它只在i=6 时打印最后一个循环的输出,然后它只打印Total_DEC2018=sum(DEC2018, DEP_DEC2018);

任何帮助将不胜感激!

谢谢, 阿杰

【问题讨论】:

  • 数据步骤开始运行后,您无法更改其代码。因此,您的 CALL SYMPUT() 语句不会对当前数据步骤的代码运行产生任何影响
  • 您知道源数据集中有哪些变量吗?它是一个常量列表吗?或者它会改变吗?如果是这样,它会如何变化?

标签: sas


【解决方案1】:

这是学习 SAS 宏时的常见问题。问题是宏处理器需要在第一次提交数据步骤执行时将&bal_mnth解析为一个值,但是直到数据步骤实际执行时才会执行CALL SYMPUT,所以在您提交代码的时候,&bal_mnth 没有可用的值。

在这种情况下,您不需要将bal_mnth 创建为数据集中的变量,因此您可以将bal_mnth = put(intck(...)) 开头的行替换为%let bal_mnth = ... 语句。 %let 在提交数据步骤时执行,因此它的值将在您需要时可用。

我提议的%let 语句需要将函数包装在至少一个SYSFUNC 调用中,这留给读者作为练习:-)

【讨论】:

    【解决方案2】:

    您似乎想要生成一系列赋值语句,例如:

    total_jun2018 = sum(jun2018, dep_jun2018); 
    total_jul2018 = sum(jul2018, dep_jul2018);
    ...
    total_jan2019 = sum(jan2019, dep_jan2019);
    

    所谓的壁纸代码。

    如果您的变量名称更简单,例如 dep1dep18,那么使用数组来处理数据会很容易。根据您当前的命名约定,生成数组语句的问题与生成一系列赋值语句的问题没有太大区别。

    您可以创建一个宏,以便使用%DO 循环来生成墙纸代码。

    %local i bal_mnth;
    %do i=0 %to &tot_bal_mnth.;
      %let bal_mnth =  %sysfunc(intnx(month,"&min_Completed_dt."d, &i-1), monyy7.);
      total_&bal_mnth = sum(&bal_mnth , Dep_&bal_mnth );
    %end;
    

    或者您可以将代码生成到带有数据步骤的文件中。

    %let tot_bal_mnth = 7;
    %let min_Completed_dt=01JUN2018;
    filename code temp;
    data _null_;
      file code;
      length bal_mnth $7 ;
      do i=0 to &tot_bal_mnth.;
        bal_mnth =  put(intnx('month',"&min_Completed_dt."d, i-1), monyy7.);
        put 'total_'  bal_mnth $7. ' = sum(' bal_mnth $7. ', Dep_' bal_mnth $7. ');';
      end;
    run;
    

    所以生成的代码文件是这样的:

    total_MAY2018 = sum(MAY2018, Dep_MAY2018);
    total_JUN2018 = sum(JUN2018, Dep_JUN2018);
    total_JUL2018 = sum(JUL2018, Dep_JUL2018);
    total_AUG2018 = sum(AUG2018, Dep_AUG2018);
    total_SEP2018 = sum(SEP2018, Dep_SEP2018);
    total_OCT2018 = sum(OCT2018, Dep_OCT2018);
    total_NOV2018 = sum(NOV2018, Dep_NOV2018);
    total_DEC2018 = sum(DEC2018, Dep_DEC2018);
    

    然后您可以使用%include 在您的数据步骤中运行它。

    data final4;
      set final3;
      by hh_no;
      %include code / source2 ;
    run;
    

    【讨论】:

      【解决方案3】:

      我想提供另一种观点:您在这里遇到的困难是由于使用了具有大量列的宽数据形状。

      您可以先从宽到长转置,而不是使用这种形状的数据,这样您就可以拥有 3 个:totaltotal_depdate,而不是有很多 total_xxx 列,每月一排。一旦采用这种格式,使用起来会容易得多,可能会让您避免求助于宏和壁纸代码。

      推荐阅读:

      Transpose wide to long with dynamic variables

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-17
        • 1970-01-01
        • 1970-01-01
        • 2021-11-02
        相关资源
        最近更新 更多