当前位置: 首页>编程语言>正文

SAS macro - 制作生存分析table1

数据预处理

1.首先清空output

dm 'log;clear;output;clear;odsresults;clear';
options mprint nodate pageno=1;
%SYSMSTORECLEAR; 

LIBNAME homework 'dir path'; *C:\Users\doc;
%include "dir path\Format.sas"; *载入format代码;

*载入上一步文件夹里的data.sas7bdat到work.dat(也许运行会更快);
*无论如何不要对源数据进行操作;
data dat1;
set homework.data;
run;

2.制定纳入排除标准

*Exclusion & inclusion criteria;
* =, ~=, lt, gt, le, ge, in, not in;
data anal;
set dat1;
    age > 21
    if age > 21;
    ** Exclude status = 2;
    if status ~= 2;
    If case = 0 then delete;
    if seq_adm1 in (0,1);
    if seq_adm2 not in (0,1);
    if OS ~= .;

3.打标签,重新分组

* 格式可参考数据库的codebook;
proc format;
value gender 1 = "Male"
             0 = "Female";
value hist 1= "Yes"
           0 = "No";
value $ char 'a1', 'a2','a3' = 'A'
             'b1', 'b2','b3' = 'B' ;
value order 1 = 'A1'
            2 = 'A2' 
            0, 9, 3-4 = 'Else';
run;


data whas500;
set hw.whas500;

*重新分组 treatment 1-5 分为 surgery 1,0 也可使用and, or等逻辑运算;
if  treatment in (1 3) then surgery = 1;
else if treatment in (2 4 5) then surgery = 0;

*替换na等;
if age in (0, 999 ,998) then age_year=.;
else TUMOR_SIZE_MM = TUMOR_SIZE;
*替换status编码;
if status = 0 then censor = 1; else censor = 0;

proc format ;
gender gender.
cvd hist. 
label gender="Gender"
      age = "Age (year)"
      ;
run;

Macro制作报表的一些思路

个人之谈,不一定是最优方法 以生存分析为例,使用macro制作下表 (主要说明解决思路,不用完全照抄)


SAS macro - 制作生存分析table1,第1张
table1
%macro make_table1(data,time,censor,catevar,contvar,ngroups);
**主体;
%mend;
** 如下制作表格:
** 输入分别为data,survival time,cencer indicator,一串分类变量,一串连续变量,连续变量分为几组;
%make_table1(whas500,timeyr,fstat(0),gender cvd afb sho av3 miord mitype,age hr sysbp diasbp bmi,4);

整体思路:

1.统一数据格式
首先输入数据有continuous和categorical variables, 这里为table1,我们需要median survival time 和log-rank test的结果,所以需要将continuous按分位数等分(一般为三等分或四等分). 这里可以使用proc rank, 然后合并所有数据.

  • SAS类似于for i in list的方法(in macro):
* list = var1 var2 var3 ...;
* 循环中依次var = var1, var2,...;
%let i=1;
%do %while (%scan(&list, &i) ne );
    %let var = %scan(&list, &i); 
    *循环体;
    %let i = %eval(&i + 1);
%end;

2.获取数据
接下来我们想获得表里的这些数据. 直接搜索SAS哪些proc能输出frequency,median survival,log rank test. 方法有很多,但是我发现proc lifetest能输出以上所有结果. 接着我还想把所有结果储存在dataset里方便整理,就要先知道每张表的名字. 这里我直接在sas help里搜索lifetest output. 可以看到The LIFETEST Procedure - Details里有Displayed outputODS table names. 可以找到如下信息确认需要的表名:

SAS macro - 制作生存分析table1,第2张
ODS table names.png
SAS macro - 制作生存分析table1,第3张
Displayed output.png
这里既可以使用statement,也可以使用ODS输出数据. 我用的ODS输出数据. 可使用的statement如下:
SAS macro - 制作生存分析table1,第4张
statement.png

ODS如下,插入proc lifetest里. proc lifetest输出的原表名为CensoredSummary,Quartiles,和HomTests,我将其储存到category,quantiles,testresults方便调用

ODS OUTPUT CensoredSummary = category 
           Quartiles = quantiles
           HomTests = testresults;
  • 有时候Result能直接显示表,我们想要导出却不知道表的名字. 这种情况直接右键properties查看Name就行. 除了Name, Template也经常会用到,可以用proc template 修改表格样式.


    SAS macro - 制作生存分析table1,第5张
    properties.png

3.拼接表格整理格式

使用proc sql或data merge. 首先横向拼接freq-median-pvalue这些结果,然后向下拼接不同变量的结果 注意几点: SAS中P-value < 0.001使用的是标签, 使用proc sql会去丢掉标签 使用proc append拼接不同变量的结果,变量长度由第一张表决定. 比如说第一个变量是Age,第二个是gender,就会变成Age,gen. 需要手动设置变量长度.

如何设置不同格式的95%CI, sd等: 在data步用字符串处理: 使用||连接不同字符,compbl()紧密连接(去掉多余空格)

mid = compbl(round(Estimate,.01)||" ("||round(LowerLimit,.01)||","||round(UpperLimit,.01)||")");

这样新变量mid就是"est (lower, upper)"的格式

4.输出好看一点的表

经处理的结果如下, order是我希望的变量顺序,最后不显示.
SAS macro - 制作生存分析table1,第6张
dataset output.png
ods rtf file = "table1.rtf";

proc report data=results spanrows;
column order varname varlevel event mid Log_rank _2Log_LR_ ; 
define order/ order noprint; 
define varname / group 'Variable';
define event /display 'Events,n';
define varlevel / display "Category"; 
define mid / display "Median Time to Death (95% CI),years" style(column)=[cellwidth=1.5in];
define Log_rank / style(column)={cellwidth=.8in } group "P-value, Log-rank test";
define _2Log_LR_ / style(column)={cellwidth=.8in} group "P-value, Partial likelihood";
title "Table 1 Patients characteristics";
run;

ods rtf close;
以上通过group合并相同单元格并自定义表头名. 另外,如果数据集是没有重复行的,比如:
SAS macro - 制作生存分析table1,第7张
example.png

gender下为空,可在proc report中使用:

compute id; *id列,逐行计算;
if variable ne ' ' then
call define('_col_','style','style=[pretext="\brdrt\brdrs\brdrw11 "]');
*实际上就是variable列非空(gender),则添加上框线;
*brdrb下框线,brdrdot点状线...;
endcomp;

另外column使用()可进行表头的层层叠加

column type ('spanned header 1' color cost ) season;
*在column里使用("\brdrb\brdrdot\brdrw5 hearder" A B C)添加下框线; 
SAS macro - 制作生存分析table1,第8张
header.png

其它琐碎细节

当连续型变量转换成分类变量,如何保持原有的变量标签(如Age (years))

data _null_;
    set &data (obs=1);
    call symputx('varlabel',vlabel(&var));
run;
*call symputx获得标签后,存为varlabel, data步新建变量作为最终输出varname = "&varlabel";

数据打过标签,如gender的male和female,希望在varlevel中显示标签(male, female)而不是数字0,1 这里有一个坑,value的label在同一列是相同的. 比如gender是0,1,cvd也是0,1,两表向下合并后会全部显示male, female.

* 在循环中;
data result_tmp;
    merge result_tmp _tmp1_ _tmp2_;
    varlevel = vvalue(&var);
run;

其余的想起来再补充

完整代码没放出,因为代码很乱没还怎么整理. 这是survival analysis这课因为大家考得很差给的bonus作业. 居然总评才加1.25分,真滴不值.快毕业了想起这回事才整理下. 想要代码可以私戳我.


https://www.xamrdz.com/lan/5ax1994448.html

相关文章: