写在前面。
新手小白,疏漏在所难免,如果您看完有所指正,那我会很感谢您。如果您看完有所收获,那是我的荣幸。
SAS编程实践---宏:按系统术语和首选术语分层次计算受试者发生不良反应(AE)例数和例次
其实是对上述文章的完善,上面文章没有最后的代码汇总
,也没解释参数意义
。
有读者要应用的话需要一块一块复制代码,很费劲,还可能复制漏了,实在是不方便。
因此本文主要内容是上篇文章的示例数据生成代码
和宏代码汇总版本
。
示例数据生成代码
proc delete data = work._ALL_;
run;
%let seed1 = 666666;
data adae;
do ii = 1 to 3;
armn = ii;
arm = cats("第",put(ii, best.) ,"组");
do jj = 1 to 100;
usubjid = cats( "X",put(ii, best.) ,"-", put(jj, z3.));
soc = cats( "SOC",put(ranbin( &seed1., 5, 0.2) + 1, best.) );
pt = cats( "PT", compress(soc, , "kd") , put(ranbin( &seed1., 10, 0.1) + 1, best.) );
AESEVN = ranbin( &seed1., 4, 0.5) + 1;
AESEV = cats(AESEVN, "级");
output;
end;
end;
run;
data adsl;
do ii = 1 to 3;
armn = ii;
arm = cats("第",put(ii, best.) ,"组");
do jj = 1 to 100;
usubjid = cats( "X",put(ii, best.) ,"-", put(jj, z3.));
output;
end;
end;
run;
宏代码汇总版本
%macro AESOCPT(
libin= ,
dtin = ,
adsl = ,
usubjid = ,
l1var = ,
l2var = ,
grpvarn = ,
rowsumyn = ,
colsumyn = ,
libout = ,
dtout = );
/*******************************************************************************************
Purpose:按系统术语、首选术语和严重程度分层次计算受试者发生不良反应(AE)例数和例次
libin:输入数据集所在逻辑库,如work;
dtin:用于分析的输入数据集,可以跟筛选条件,也可以提前处理好,如adlb(where = FASFL = "是");
adsl:adsl数据集,用于确定受试者数量;
usubjid:受试者编号,用于确定受试者数量;
l1var:层级1的变量,如器官系统术语,AEBODSYS;
l2var:层级2的变量,如首选术语,AEDECOD;
grpvarn:受试者实验分组变量,数值型;
rowsumyn:指定是否计算合计列,取值限定为Y或者N;
colsumyn:指定是否计算首行合计,取值限定为Y或者N;
libout:输出数据集所在逻辑库,如work;
dtout:输出数据集名称,如Table1;
**************************************************************************************************/
*_1. pre-processing;
*_1.1 macro variables;
*subjid number;
proc sql noprint;
select count(distinct &grpvarn.) , count(distinct &usubjid.) into: grpnum, : SUBN999 from &adsl.;
quit;
%put 受试者数量:&SUBN999. 分组数量:&grpnum.;
%do xx = 1 %to &grpnum.;
proc sql noprint;
select count(distinct &usubjid.) into:SUBN&xx. from &adsl. where &grpvarn. = &xx.;
quit;
%put &grpvarn. = &xx.组的受试者数量: &&SUBN&xx.;
%end;
*_1.2 input datasets processing;
data stdt0;
set &libin..&dtin.;
run;
proc sort data=stdt0 out=&l1var._ nodupkey;
by &l1var.;
run;
data &l1var.n;
set &l1var._;
&l1var.n = _N_;
proc sort;
by &l1var.;
run;
proc sort data=stdt0;
by &l1var.;
run;
*_1.2.1 for times of case;
data times1;
merge stdt0
&l1var.n;
by &l1var.;
run;
data times2;
set times1;
&l1var. = "合计";
&l1var.n = 0;
&l2var. = "合计";
run;
*_1.2.2 for number of case;
data case1;
merge stdt0
&l1var.n;
by &l1var.;
run;
proc sort data=case1 out=cs1nodup nodup dupout=cs1dup;
by &usubjid. &l1var.n &l1var. &l2var.;
run;
proc sort data=case1 out=cs2nodup nodup dupout=cs2dup;
by &usubjid. &l1var.n &l1var.;
run;
data case2;
set cs2nodup;
&l1var. = "合计";
&l1var.n = 0;
&l2var. = "合计";
run;
*_2.stat step;
*_2.1 number of case;
%do aa = 1 %to &grpnum.;
proc sql noprint;
create table ST_&aa. as
select &l1var.n, &l1var., "合计" as &l2var.,
cats(sum(&grpvarn. = &aa.), "(", put(sum(&grpvarn. = &aa.)/&&SUBN&aa.*100, 8.2), ")") as CASE_&aa.,
sum(&grpvarn. > 0) + 0.2 as seq1
from cs1nodup
group by &l1var.n, &l1var.
union
select &l1var.n, &l1var., &l2var.,
cats(sum(&grpvarn. = &aa.), "(", put(sum(&grpvarn. = &aa.)/&&SUBN&aa.*100, 8.2), ")") as CASE_&aa.,
sum(&grpvarn. > 0) +0.1 as seq1
from cs1nodup
group by &l1var.n, &l1var., &l2var.
union
select &l1var.n, &l1var., "合计" as &l2var.,
cats(sum(&grpvarn. = &aa.), "(", put(sum(&grpvarn. = &aa.)/&&SUBN&aa.*100, 8.2), ")") as CASE_&aa.,
sum(&grpvarn. > 0) + 1 as seq1
from case2
group by &l1var.n, &l1var.
;
quit;
proc sort data= ST_&aa.;
by &l1var.n &l1var. &l2var.;
run;
%end;
*_2.2 times of case;
%do aa = 1 %to &grpnum.;
proc sql noprint;
create table ST_&aa._ as
select &l1var.n, &l1var., "合计" as &l2var.,
cats(sum(&grpvarn. = &aa.)) as CASE_&aa._ ,
sum(&grpvarn. > 0) + 0.2 as seq2
from times1
group by &l1var.n, &l1var.
union
select &l1var.n, &l1var., &l2var.,
cats(sum(&grpvarn. = &aa.)) as CASE_&aa._ ,
sum(&grpvarn. > 0) +0.1 as seq2
from times1
group by &l1var.n, &l1var., &l2var.
union
select &l1var.n, &l1var., "合计" as &l2var.,
cats(sum(&grpvarn. = &aa.)) as CASE_&aa._ ,
sum(&grpvarn. > 0) + 1 as seq2
from times2
group by &l1var.n, &l1var.
;
quit;
proc sort data= ST_&aa._;
by &l1var.n &l1var. &l2var.;
run;
%end;
*_2.3 caculation of each row;
%if %sysfunc(upcase(&rowsumyn.) ) = %str(Y) %then
%do;
%put WARNING: 已经计算每行合计;
*_2.3.1 caculation of each row for number of case;
proc sql noprint;
create table ST_99 as
select &l1var.n, &l1var., "合计" as &l2var., 1 as idid,
cats(sum(&grpvarn. > 0), "(", put(sum(&grpvarn. > 0)/&SUBN999.*100, 8.2), ")") as CASE_99,
sum(&grpvarn. > 0) + 0.2 as seq1
from cs1nodup
group by &l1var.n, &l1var.
union
select &l1var.n, &l1var., &l2var., 2 as idid,
cats(sum(&grpvarn. > 0), "(", put(sum(&grpvarn. > 0)/&SUBN999.*100, 8.2), ")") as CASE_99,
sum(&grpvarn. > 0) + 0.1 as seq1
from cs1nodup
group by &l1var.n, &l1var., &l2var.
union
select &l1var.n, &l1var., "合计" as &l2var., 3 as idid,
cats(sum(&grpvarn. > 0), "(", put(sum(&grpvarn. > 0)/&SUBN999.*100, 8.2), ")") as CASE_99,
sum(&grpvarn. > 0) + 1 as seq1
from case2
group by &l1var.n, &l1var.
;
run;
proc sort data= ST_99;
by &l1var.n &l1var. &l2var.;
run;
*_2.3.2 caculation of each row for times of case;
proc sql noprint;
create table ST_99_ as
select &l1var.n, &l1var., "合计" as &l2var., 1 as idid,
cats(sum(&grpvarn. > 0) ) as CASE_99_,
sum(&grpvarn. > 0) + 0.2 as seq2
from times1
group by &l1var.n, &l1var.
union
select &l1var.n, &l1var., &l2var., 2 as idid,
cats(sum(&grpvarn. > 0) ) as CASE_99_,
sum(&grpvarn. > 0) + 0.1 as seq2
from times1
group by &l1var.n, &l1var., &l2var.
union
select &l1var.n, &l1var., "合计" as &l2var., 3 as idid,
cats(sum(&grpvarn. > 0) ) as CASE_99_,
sum(&grpvarn. > 0) + 1 as seq2
from times2
group by &l1var.n, &l1var.
;
run;
proc sort data= ST_99_;
by &l1var.n &l1var. &l2var.;
run;
%end;
%else
%do;
%put WARNING: 不计算每行合计;
%end;
*_2.4 caculation of each column;
data _0&dtout.;
merge ST_:
;
by &l1var.n &l1var. &l2var.;
%if %sysfunc(upcase(&colsumyn.) ) = %str(Y) %then
%do;
%put WARNING: 已经计算每列合计;
%end;
%else
%do;
%put WARNING: 不计算每列合计;
if &l1var.n = 0 then
delete;
%end;
proc sort;
by &l1var.n descending seq1 descending seq2;
run;
run;
*_3 processing step of stat;
data _1&dtout.;
set _0&dtout.;
by &l1var.n descending seq1 descending seq2;
if first.&l1var.n or first.&l1var. then
&l1var. = &l1var.;
else &l1var. = " "||&l2var.;
keep &l1var. CASE_:;
run;
* _4.output steps;
proc contents data= _1&dtout. out= _1outs noprint;
proc sort;
by varnum;
run;
proc sql noprint;
select count(distinct NAME) , NAME into:varn,:col1-:col99 from _1outs;
quit;
data &libout..&dtout.;
set _1&dtout.;
%do ii = 1 %to &varn.;
if &&col&ii. = "0(0.00)" then
&&col&ii. ="0";
%let jj = %eval(&ii. - 1);
rename &&col&ii. = C&jj.;
%end;
run;
proc datasets lib=work noprint;
delete &l1var._ &l1var.n times: case: cs: st: _:;
run;
%mend;
%AESOCPT(libin=work ,
dtin = adae ,
adsl = adsl ,
usubjid = usubjid ,
l1var =soc ,
l2var = pt,
grpvarn = armn,
rowsumyn = Y,
colsumyn =Y ,
libout =work ,
dtout = table);
以上。