【问题标题】:Call symput in SAS with loop使用循环在 SAS 中调用 symput
【发布时间】:2019-07-23 19:58:27
【问题描述】:

我有如下代码,我想在数据测试中创建一个 if 语句 [在新列中,我们称之为标志],我可以使用宏定义的五分位数 [来自宏中的 proc 单变量步骤 1]。最后我想看看每条记录是否在定义的分位数中,如果不是,标志应该是别的东西。

我在定义宏变量的步骤上停了下来。如何命令 SAS 将 Q1 定义为 proc 单变量输出的 pct10?

data test;
do x=1 to 100;
output;
end;
x=.;
output; output;
run;

example %quint(test,x,10 20 30 70)

%macro quint(input=,var=, pcts=);

/* calculate the cutpoints for the quintiles */
proc univariate data=&input;
  var &var;
  output out=quintile pctlpts=&pcts pctlpre=pct;
run;


/* write the quintiles to macro variables */
data _null_;
set quintile;
%do i=1 %to %sysfunc(countw(&pcts));
call symput(cats("Q",&i),cats("pct",%scan(&pcts,&i,' ')));
%put "&&Q&i";
%end;

run;

there should be data test with new column flag based on macrovariables created from proc univariate Q1 to Qx

%mend quint;

【问题讨论】:

    标签: sas undefined sas-macro


    【解决方案1】:

    不需要宏变量。只需使用 PROC UNIVARIATE 生成的实变量即可。

    %macro quint(input=,output=,invar=,outvar=, pcts=);
    
    * calculate the cutpoints for the quintiles ;
    proc univariate noprint data=&input;
      var &invar;
      output out=cutpoints pctlpts=&pcts pctlpre=__pct;
    run;
    
    * Use cutpoints to calculate the RANK for each value ;
    data &output ;
      if _n_=1 then set cutpoints ;
      array cutpoints __pct: ;
      drop __pct: ;
      set &input;
      if missing(&invar) then &outvar=0;
      else do &outvar=1 to dim(cutpoints) while(&invar>cutpoints[&outvar]); end;
    run;
    
    %mend quint;
    

    因此,使用您的示例数据,我们可以像这样调用宏:

    %quint(input=test,output=want,invar=x,outvar=rank,pcts=10 20 30 70)
    

    为了测试它,让我们看看 X 的最小/最大值分配给每个“等级”。

    proc means n min max data=want nway;
      class rank ;
      var x;
    run;
    

    输出:

    【讨论】:

      【解决方案2】:

      我猜是另一种方式:

      这假定百分位数是按升序指定的 - 否则会给出错误的结果。

      %macro quint(input=,var=, pcts=);
      
      proc univariate data=&input noprint;
        var &var;
        output out=quintile pctlpts=&pcts pctlpre=pct;
      run;
      
      %let ii = 1;
      
      data pcts;
        if _N_ = 1 then set quintile;
        set &input;
      
        %do %while (%scan(&pcts, &ii) ne );
          %let q = %scan(&pcts, &ii);
          %if &ii = 1 %then %do;
            if x < pct&q then qunitile = &q;
          %end;
          %else %do;
            else if x < pct&q then qunitile = &q;
          %end;
          %let ii = %eval(&ii + 1);
        %end;
      
        drop pct:;
      
      run;
      
      proc print;
      run;
      
      %mend quint;
      
      %quint(input=test,var=x,pcts=10 20 30 70);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-18
        • 1970-01-01
        • 1970-01-01
        • 2019-02-16
        • 1970-01-01
        相关资源
        最近更新 更多