SAS Расчет процентилей и сохранение в макропеременную

У меня есть следующий код для вычисления процентилей.

proc univariate data=sashelp.cars;
  var Horsepower 
  output pctlpre=P_ pctlpts= 50, 75 to 100 by 5;
run;

Я хотел бы назначить эти процентили макропеременной (то есть 1 макропеременная на процентиль) на лету. Есть ли какой-нибудь умный способ сделать это?


person user3507584    schedule 06.02.2020    source источник
comment
Ваш предполагаемый результат неясен - 1 макропеременная, содержащая список процентилей и значений, 1 макропеременная на точку процентиля ...?   -  person user667489    schedule 06.02.2020
comment
Один макрос на значение процентиля   -  person user3507584    schedule 06.02.2020


Ответы (3)


Что означает «умный способ сделать это»? Что вы будете делать с макросами, как вы их называете?

proc univariate data=sashelp.cars noprint;
   var Horsepower;
   output pctlpre=P_ pctlpts= 50, 75 to 100 by 5;
   run;
proc print;
   run;
data _null_;
   set;
   array P_ P_:;
   do over p_;
      call symputx(vname(p_),p_);
      end;
   stop;
   run;
%put _user_;

введите здесь описание изображения

Основываясь на данных OP о том, что они на самом деле делают, нет необходимости помещать данные в макропеременные. По моему мнению, никогда не бывает «умным» помещать данные в макропеременные, когда эти переменные будут использоваться в расчетах.

Это создает новые переменные CAP_: ограниченные значением &p.

%let p=90;
ods select none;
ods output summary=ptile;
proc means data=sashelp.cars stackods p&P.;
   run;
ods output close;
ods select all;
proc print;
   run;
/*Flip the rows into 1 obs.  Vars with prefix P&P._*/
proc transpose data=ptile out=ptile2(drop=_:) prefix=P&P._;
   var P&P.;
   id variable;
   run;
/*Flip the rows to create new CAP_ variables.  Just for the names*/
proc transpose data=ptile out=cap(drop=_:) prefix=Cap_;
   var P&P.;
   id variable;
   run;
/*create capped variables*/
data capped;
   set sashelp.cars;
   array _v _numeric_;
   /*Create array of new variables CAP_*/
   if 0 then set cap; 
   array _cap cap_:;
   call missing(of _cap[*]);
   /*Create array of Ptile variables*/
   if _n_ eq 1 then set ptile2;
   array _tile P&P._:; 
   *drop P&P._:;
   do over _v;
      _cap = min(_tile,_v);
      end;
   run;
proc print;
   run;

введите здесь описание изображения

person data _null_    schedule 06.02.2020
comment
Я выбираю это, так как оно выполняет работу с меньшим количеством строк кода (так что в некотором смысле это самое умное решение..) - person user3507584; 06.02.2020
comment
В общем случае помещать данные в макропеременные — плохая идея. Я еще раз спрошу, зачем тебе это? - person data _null_; 07.02.2020
comment
Я создавал переменные, которые являются одной и той же переменной, но ограничены разными процентилями. В R (просто, лучше всего в data.table) я мог бы сделать что-то вроде: table$capped_var <- ifelse(table$original_var > quantile(table$original_var,.99), quantile(table$original_var,.99),table$original_var) - person user3507584; 07.02.2020

Может быть не так умно, но будет работать, я думаю.

proc univariate data=sashelp.cars;
  var Horsepower;
  output out=table pctlpre=P_ pctlpts= 50, 75 to 100 by 5;
run;

proc sql noprint;
   select 'call symput('|| "'" ||strip(name)||"'," || strip(name) || ");"  
   into:name_list separated by ' ' 
   from dictionary.columns 
   where libname ="WORK" and memname="TABLE";
quit;

data _null_;
   set table;
   &name_list;
run;

%put _ALL_;

Proc sql генерирует код на лету: call symput('P_50',P_50); call symput('P_75',P_75); call symput('P_80',P_80); call symput('P_85',P_85); call symput('P_90',P_90); call symput('P_95',P_95); call symput('P_100',P_100);

ВЫХОД:

ГЛОБАЛЬНЫЙ P_100 500

ГЛОБАЛЬНЫЙ P_50 210

ГЛОБАЛЬНЫЙ P_75 255

ГЛОБАЛЬНЫЙ P_80 275

ГЛОБАЛЬНЫЙ P_85 295

ГЛОБАЛЬНЫЙ P_90 302

ГЛОБАЛЬНЫЙ P_95 340

person Alexey Sigida    schedule 06.02.2020

Вот способ сделать это, используя только один proc sql:

proc univariate noprint data=sashelp.class;
  var height; 
  output out=percentiles pctlpre=P_ pctlpts= 50, 75 to 100 by 5;
run;

proc sql noprint;
  select 
    name, 
    cats(':',name)
  into 
    :COL_NAMES separated by ',', 
    :MVAR_NAMES separated by ','
  from sashelp.vcolumn 
  where 
    libname = "WORK" 
    and memname = "PERCENTILES"
  ;
  select &COL_NAMES into &MVAR_NAMES
  from percentiles;
quit;

Результат: 1 макропеременная на процентиль с теми же именами, что и у одномерного вывода.

person user667489    schedule 06.02.2020