使用循环在 SAS 中调用 symput
Call symput in SAS with loop
我有如下代码,我想在数据测试中做一个 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;
不需要宏变量。只需使用 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 的 min/max 值分配给每个 "rank"。
proc means n min max data=want nway;
class rank ;
var x;
run;
输出:
我猜还有另一种方法:
这假设百分位数是按升序指定的 - 否则它可能会给出错误的结果。
%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);
我有如下代码,我想在数据测试中做一个 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;
不需要宏变量。只需使用 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 的 min/max 值分配给每个 "rank"。
proc means n min max data=want nway;
class rank ;
var x;
run;
输出:
我猜还有另一种方法:
这假设百分位数是按升序指定的 - 否则它可能会给出错误的结果。
%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);