Ранжирование динамического количества столбцов в SAS - PullRequest
0 голосов
/ 23 октября 2018

У меня есть набор данных с ключом и количеством баллов для различных факторов (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?).

Любая помощь очень ценится.

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Для ранжирования по строкам, я думаю, это то, что вы хотите.Если вы хотите по-разному называть переменные 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;

enter image description here

0 голосов
/ 23 октября 2018

Вы ранжируете столбцы или строки?Функция ORDINAL ранжирует строки.Похоже, вы должны использовать PROC 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;

enter image description here

Макрос 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;
...