宏程序在我们日常编程中被普遍使用。项目中的很多输出内容都是相同的标准和模板,如果每次都手动编写程序,这样的效率未免有些低下。我写宏程序这系列文章的目的,就是将工作中可能遇到的宏程序积累下来,以方便下次调用。这一系列要写多少以及怎么写,我自己也不太确定,就先开始写起来。
相同的输出可以通过不同的程序来实现,与之对应的宏程序的实现也并非固定。我先尽量为每种输出形式完成一种形式,至于丰富实现方法,以后再补充。文章的框架是先以普通的SAS程序实现输出,最后将程序封装成宏程序,方便使用。
我先介绍输出描述性统计量的宏程序。描述性统计量的输出在临床试验统计分析中非常普遍,每一个临床试验的SAP中都应该有类似的语句:
Descriptive statistics on continuous measurements will include means, medians, standard deviations, quartiles(Q1, Q3) and minimum and maximum, while categorical data will be summarized using frequency counts and percentages.
至于如何实现描述性统计量的输出,从我接触的项目中来看,大致有3种实现途径:
- Proc Means
- Proc Univariate
- Proc Summary
今天我来介绍Proc Summary的实现方法,我以SASHELP.CLASS数据集作为分析数据集,输出不同性别同学的身高的描述性统计量。首先,我们先看一下描述性统计量的模板,关于模板各个公司应该大同小异:
我这边就不介绍具体的SAS语法了,直接看程序如何实现:
proc summary data = sashelp.class;
class sex;
var height;
output out=height1 n=n mean=mean median=median std=std min=min max=max q1=q1 q3=q3;
run;
以上代码将各分组以及分组汇总的统计量输出到Height1数据集中:
描述性统计量获取后,需要整理成模板显示的形式。显然,模板显示的竖向排列,而输出的数据集中是横向排列的。这里实现的方法一般有两种,第一,Proc Tranpose语句将横向数据转变为纵向数据;第二,在Data步中使用Ouput语句实现纵向输出。
这里,我采用Proc Tranpose进行实现。关于各个统计量的保留的小数位数,不同的公司可能有不同的要求,在这里min、max先保留一位,mean、std、q1、q3先保留两位。小数位数在最后的宏程序中可以使用宏参数进行控制。
data height2;
set height1;
where not missing(sex);
length v1-v6 $50;
if n >. then v1=strip(put(n, 4.0)); else v1 = "0";
if mean >. then v2=strip(put(mean,8.2)); else v2="-";
if std>. then v3=strip(put(std,8.2)); else v3="-";
if median>. then v4=strip(put(median,8.2)); else v4="-";
if nmiss(q1,q3) =0 then v5=strip(put(q1,8.2))||", "||strip(put(q3,8.2)); else v5="-, -";
if nmiss(min,max) =0 then v6=strip(put(min,8.1))||", "||strip(put(max,8.1)); else v6="-, -";
run;
proc transpose data = height2 out=height3;
var v1 -v6;
run;
输出结果如下:
这里输出的整体内容已经很完善了,但是第一列没有具体统计量名称,需要进一步补充,这里可以通过建立Format进行实现。
proc format;
value $stat
"v1" = "n"
"v2" = "Mean"
"v3" = "SD"
"v4" = "Median"
"v5" = "Q1, Q3"
"v6" = "Min, Max"
;
run;
data out;
set height3;
_name_ = put(_name_, $stat.);
run;
以上就是整个输出描述性统计量的过程,这是一个整体的框架,一些细节可能不同公司有不同要求,具体细节读者可以自行补充。考虑到一张Table可能出多个变量的描述性统计量,可以添加一个变量记录表属于具体的表的第几部分,也可以增加记录同一部分中的统计量排列顺序的变量。
将以上程序封装成宏程序,具体如下:
%macro Summary(indt=, outdt=, trtvar=, anavar=, dplace=, sec=);
proc summary data = &indt.;
class &trtvar.;
var &anavar.;
output out=&anavar.1 n=n mean=mean median=median std=std min=min max=max q1=q1 q3=q3;
run;
data &anavar.2;
set &anavar.1;
where not missing(&trtvar.);
length v1-v6 $50;
%let dplace1 = %eval(&dplace. +1);
if n >. then v1=strip(put(n, 4.0)); else v1 = "0";
if mean >. then v2=strip(put(mean,8.&dplace1.)); else v2="-";
if std>. then v3=strip(put(std,8.&dplace1.)); else v3="-";
if median>. then v4=strip(put(median,8.&dplace1.)); else v4="-";
if nmiss(q1,q3) =0 then v5=strip(put(q1,8.&dplace1.))||", "||strip(put(q3,8.&dplace1.)); else v5="-, -";
if nmiss(min,max) =0 then v6=strip(put(min,8.&dplace.))||", "||strip(put(max,8.&dplace.)); else v6="-, -";
run;
proc transpose data = &anavar.2 out=&anavar.3;
var v1 -v6;
run;
data &outdt;
set &anavar.3;
_name_ = put(_name_, $stat.);
sec = &sec.;
rownum=_n_;
run;
%mend;
%Summary(indt=sashelp.class, outdt=out, trtvar=sex, anavar=height, dplace=1, sec=1);
输出结果如下:
以上。
若有疑问,欢迎评论区交流!