option mprint;
%macro quantify(data=,byvarn=,byvar=,stat=,ordpct=);
proc sql noprint;
select max(paramn)into :paramn from &data.;
quit;
%put ¶mn.;
%do par=1 %to %eval(¶mn.+1);
proc sort data=&data.(where=(paramn=&par.)) out=ad;by &byvarn. &byvar.;run;
%let dataset=%sysfunc(open(ad));
%let nobs=%sysfunc(attrn(&dataset.,nobs));
%let cl=%sysfunc(close(&dataset.));
%put &nobs;
%if &nobs. ne 0 %then %do;
data length;
set ad;
length=length(compress(scan(put(aval,best.),2,".")));
if find(put(aval,best.),".")=0 then do;leng=0.1;pleng=10.1;format pleng 4.1;end;
else do;leng=0.1*0.1**length;
pleng=10.1+0.1*length;
mpleng=10.0+0.1*length;
end;
keep aval leng pleng mpleng;
proc sort;by leng;
proc sort nodupkey;by leng;
run;
proc sql noprint;
select leng into :leng from length;
select pleng into :pleng from length;
select mpleng into :mpleng from length;
quit;
ods output summary=st1;
proc means data=ad &stat.;
var aval;
by &byvarn. &byvar.;
run;
ods output close;
proc transpose data=st1 out=st2 prefix=col_;
var aval:;
by &byvarn. &byvar.;
run;
data st3;
length pct item $ 200;
set st2;
tot=input(symget(compress("n"||put(%scan(&byvarn.,1," "),best.))),best.);
item=scan(_name_,2,"_");
%if &leng.>=0.0001 %then %do;
if _label_ in ("N","例数") then do;miss=strip(put(tot-col_1,best.));pct=strip(put(col_1,best.))||" ("||strip(miss)||")";end;
if _label_ in ("均值","中位数","四分位数下限","四分位数上限") then do;pct=strip(put(round(col_1,&leng.),&pleng.));end;
if _label_ in ("标准差") then do;pct=strip(put(round(col_1,&leng.*0.1),%sysevalf(&pleng.+0.1)));end;
if _label_ in ("最小值","最大值") then do;
%if &leng.>=0.1 %then %do;pct=strip(put(col_1,best.));%end;
%else %do;pct=strip(put(col_1,&mpleng.));%end;
end;
%end;
%if &leng.=0.0001 %then %do;
if _label_ in ("标准差") then do;pct=strip(put(round(col_1,&leng.),&pleng.));end;
if _label_ in ("最小值","最大值") then do;pct=strip(put(col_1,&mpleng.));end;
%end;
%if &leng.<0.0001 %then %do;
if _label_ in ("N","例数") then do;miss=strip(put(tot-col_1,best.));pct=strip(put(col_1,best.))||" ("||strip(miss)||")";end;
else pct=strip(put(round(aval_mean,0.0001),8.4));
%end;
if length(compress(scan(pct,2,".")))>4 then pct=strip(put(round(input(pct,best.),0.0001),8.4));
proc sort;by &byvar. param;
run;
proc transpose data=st3 out=st4;
id item;
var pct;
by &byvarn. &byvar.;
run;
%let ord=%sysfunc(sum(%sysfunc(countc(%sysfunc(strip(%sysfunc(compbl("&byvarn.")))), ' '))+1));
%let item=%sysfunc(sum(%sysfunc(countc(%sysfunc(strip(%sysfunc(compbl("&byvar.")))), ' '))+1));
data st5;
length item: col1 $100;
set st4;
%do i=2 %to &ord.;
ord%eval(&i.-1)=%scan(%sysfunc(compbl("&byvarn.")),&i.," ");
item%eval(&i.-1)=%scan(%sysfunc(compbl("&byvar.")),&i.," ");
%end;
group=%scan(%sysfunc(compbl("&byvarn.")),1," ");
item&ord.="n(miss)";col1=n;ord99=%index("&ordpct.",1);output;
item&ord.="Mean (SD)";col1=strip(mean)||" ("||strip(StdDev)||")";ord99=%index("&ordpct.",2);output;
item&ord.="Median";col1=Median;ord99=%index("&ordpct.",3);output;
if %index("&ordpct.",4)^=0 then do;
item&ord.="Min, Max";col1=strip(Min)||" ,"||strip(Max);ord99=%index("&ordpct.",4);output;
end;
if %index("&ordpct.",5)^=0 then do;
item&ord.="Min, Max";col1=strip(Q1)||" ,"||strip(Q3);ord99=%index("&ordpct.",5);output;
end;
keep group item: ord: col1;
proc sort;by ord: item:;
run;
proc transpose data=st5 out=st6 prefix=col;
id group;
by ord: item:;
var col1;
run;
data st7;
set st6;
by ord: item:;
if not first.ord1 then item1="";
drop _name_;
run;
%end;
%else %do;
%let ord=%sysfunc(sum(%sysfunc(countc(%sysfunc(strip(%sysfunc(compbl("&byvarn.")))), ' '))+1));
%let item=%sysfunc(sum(%sysfunc(countc(%sysfunc(strip(%sysfunc(compbl("&byvar.")))), ' '))+1));
proc sql noprint;
select count(distinct(%scan(%sysfunc(compbl("&byvarn.")),1," "))) into:col from &data. where %scan(%sysfunc(compbl("&byvarn.")),1," ")^=.;
quit;
%put &col.;
data st7;
%do i=2 %to &ord.;
ord%eval(&i.-1)=.;
item%eval(&i.-1)="";
%end;
%do col=1 %to &col.;
col&col.="";
%end;
ord99=.;
item&ord.="";
run;
%end;
data all;
length item: col: $200;
set all st7 ;
run;
%end;
%mend;
data all;run;
%quantify(data=ad3,
byvarn= ,/*分组变量n,按顺序排列,从第二个开始要作为数据集的排序变量*/
byvar= ,/*分组变量,按顺序排列,从第二个开始要作为输出表格的item*/
stat= ,/*要计算的统计量*/
ordpct= /*rd= 统计量在table的排序n(miss)=1 Mean(SD)=2 Median=3 Min,Max=4 q1,q3=5对应的顺序*/
);
输出如下结构: