【问题标题】:Ranking dynamic number of columns in SAS对SAS中的动态列数进行排名
【发布时间】:2018-10-23 21:02:38
【问题描述】:

我有一个数据集,其中包含一个键和多个不同因素(A、B、C、D...)的分数。它看起来像这样:

data scores;
input KEY A B C D E F G H;
cards; 
1 1 2 4 4 4 9 9 7   
2 1 2 3 4 5 6 7 8   
3 7 8 9 9 6 5 5 4   
4 4 9 9 7 7 8 5 1 
run;

我正在尝试获得类似于以下输出的每个因素的排名:

proc sql;
create table scorerank as
select   *
        ,(ordinal(1,A,B,C,D,E,F,G,H)) as ScoreRank1
        ,(ordinal(2,A,B,C,D,E,F,G,H)) as ScoreRank2
        ,(ordinal(3,A,B,C,D,E,F,G,H)) as ScoreRank3
        ,(ordinal(4,A,B,C,D,E,F,G,H)) as ScoreRank4
        ,(ordinal(5,A,B,C,D,E,F,G,H)) as ScoreRank5
        ,(ordinal(6,A,B,C,D,E,F,G,H)) as ScoreRank6
        ,(ordinal(7,A,B,C,D,E,F,G,H)) as ScoreRank7
        ,(ordinal(8,A,B,C,D,E,F,G,H)) as ScoreRank8
from scores;
quit;

我的问题是每次都有动态数量的因素。这意味着,序数函数中的一个动态列表和一个 ScoreRankX 上升到分数的计数。

我已经尝试这样做作为开始:

%let num = 8;
%let factors = A,B,C,D,E,F,G,H;

data datarank;
set scores;
do i = 1 to &num.;
ScoreRank&num. = (ordinal(&num.,&factors.));
end;
run;

我可以在每个代码的开头更改 %let 语句,但我正在尝试使排名部分更加自动化。知道如何改进我正在处理的上述代码吗?目前它仅使用最后一个等级和“i”输出错误(即使我有 do 循环?)。

非常感谢任何帮助。

【问题讨论】:

    标签: sas


    【解决方案1】:

    对于跨行排名,我认为这就是您想要的。如果您想以不同的方式命名 RANK 变量,您可以使用 EXPAND_VARLIST,就像我在其他答案中所做的那样。那么你就不需要 &num。

    %let num = 8;
    data datarank;
       set scores;
       array score[*] a--h;
       array Rank[&num];
       do i = 1 to dim(rank);
          Rank[i] = ordinal(i,of score[*]);
          end;
       drop i;
       run;
    proc print;
       run;
    

    【讨论】:

      【解决方案2】:

      您是对列还是行进行排名? ORDINAL 函数对行进行排名。似乎您应该使用 PROC RANK 和 rank 列。 PROC RANK 的默认设置是对排名使用相同的变量,这在大多数情况下运行良好,但您似乎想要新名称,因此我包含了该方法。

      data scores;
         input KEY A B C D E F G H;
         cards; 
      1 1 2 4 4 4 9 9 7   
      2 1 2 3 4 5 6 7 8   
      3 7 8 9 9 6 5 5 4   
      4 4 9 9 7 7 8 5 1 
         run;
      proc print;
         run;
      %let ranks=%expand_varlist(data=ranks,var=a-numeric-h,expr=cats('Rank_',_name_));
      proc rank out=ranks ties=mean;
         var a--h;
         ranks &ranks;
         run;
      proc print;
         run;
      

      宏 EXPAND_VARLIST

      %macro
         expand_varlist /*Returns an expanded variable list and optionally creates an indexed data set of variable names*/
            (
               data  = _LAST_,            /*[R]Input data*/
               var   = _ALL_,             /*[R]Variable List expanded*/
               where = 1,                 /*[R]Where clause to subset OUT=, useful for selecting by a name suffix e.g. where=_name_ like '%_Status'*/
               expr  = nliteral(&name),   /*[R]An expression that can be used to modify the names in the expanded list*/
               keep  = ,                  /*[O]Keep data set option for DATA=*/
               drop  = ,                  /*[O]Drop data set option for DATA=*/
               out   = ,                  /*[O]Output data indexed by _NAME_ and _INDEX_*/
               name  = _NAME_,            /*[R]Name of the variable name variable in the output data set*/
               label = _LABEL_,           /*[R]Name of the variable name label variable in the output data set*/
               index = _INDEX_,           /*[R]Name of the variable index variable in the output data set*/
               dlm   = ' '                /*[R]List delimiter*/
            );
         %local m i;
         %let i=&sysindex;
         %let m=&sysmacroname._&i;
         %do %while(%symexist(&m));
            %let i = %eval(&i + 1);
            %let m=&sysmacroname._&i;
            %end;
         %put NOTE: &=m is a unique symbol name;
         %local rc &m code1 code2 code3 code4;
         %if %superq(out) ne %then %let code3 = %str(data &out(index=(&index &name)); set &out; &index+1; run;);
         %else %do;
            %let out=%str(work._deleteme_);
            %let code3 = %str(proc delete data=work._deleteme_; run;);
            %end;
         %let code1 = %str(options notes=0; proc transpose name=&name label=&label data=&data(obs=0 keep=&keep drop=&drop) out=&out(where=(&where)); var &var; run;);
         %let code2 = %str(proc sql noprint; select &expr into :&m separated by &dlm from &out; quit;);
         %let code4 = %str(options notes=1;);
         %let rc=%sysfunc(dosubl(&code1 &code2 &code3 &code4));
      &&&m.
         %mend expand_varlist;
      

      【讨论】:

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