使用循环调用SAS中的symput

使用循环调用SAS中的symput,sas,undefined,sas-macro,Sas,Undefined,Sas Macro,我有如下代码,我想在数据测试中做一个if语句[在新列中,让我们称之为flag],在这里我可以使用宏定义的五分位数[来自宏中的proc单变量步骤1]。最后,我想看看每个记录是否属于定义的分位数,如果不是,标志应该是其他的 我停止了定义宏变量的步骤。我如何命令SAS将Q1定义为pct10,它是proc单变量输出 data test; do x=1 to 100; output; end; x=.; output; output; run; example %quint(test,x,10 20 3

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

我停止了定义宏变量的步骤。我如何命令SAS将Q1定义为pct10,它是proc单变量输出

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单变量生成的实变量

%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;
输出:


不需要宏变量。只需使用PROC单变量生成的实变量

%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;
输出:


我想还有另一种方法:

这假设百分位数是按升序指定的,否则可能会给出错误的结果

%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);

我想还有另一种方法:

这假设百分位数是按升序指定的,否则可能会给出错误的结果

%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);