SAS编程宏处理1--描述性统计量的输出

宏程序在我们日常编程中被普遍使用。项目中的很多输出内容都是相同的标准和模板,如果每次都手动编写程序,这样的效率未免有些低下。我写宏程序这系列文章的目的,就是将工作中可能遇到的宏程序积累下来,以方便下次调用。这一系列要写多少以及怎么写,我自己也不太确定,就先开始写起来。

相同的输出可以通过不同的程序来实现,与之对应的宏程序的实现也并非固定。我先尽量为每种输出形式完成一种形式,至于丰富实现方法,以后再补充。文章的框架是先以普通的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种实现途径:

  1. Proc Means
  2. Proc Univariate
  3. 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数据集中:


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;

输出结果如下:


Height2
Height3

这里输出的整体内容已经很完善了,但是第一列没有具体统计量名称,需要进一步补充,这里可以通过建立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;

Out

以上就是整个输出描述性统计量的过程,这是一个整体的框架,一些细节可能不同公司有不同要求,具体细节读者可以自行补充。考虑到一张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);

输出结果如下:


Out

以上。
若有疑问,欢迎评论区交流!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容