臨床試驗(yàn)TFL輸出中,有一類頻數(shù)匯總表的各條目是包含層級(jí)關(guān)系的。例如,之前介紹的SAS編程:按SOC和PT類別匯總AE的受試者發(fā)生率躺盛,單個(gè)SOC下,可能會(huì)對(duì)應(yīng)多個(gè)PT咙鞍。
對(duì)于具有層級(jí)關(guān)系的頻數(shù)匯總表房官,常規(guī)的處理方式是,先對(duì)各個(gè)層級(jí)進(jìn)行單獨(dú)統(tǒng)計(jì)续滋,之后再匯總進(jìn)行排序翰守,前面提到的AE SOCPT表格就是這樣處理的。
今天疲酌,介紹另一種方法蜡峰,我給這種方法取名為層級(jí)拼接法。層級(jí)拼接法的本質(zhì)是朗恳,將多層級(jí)轉(zhuǎn)化為單層級(jí)進(jìn)行處理湿颅。這個(gè)方法的效率要比各個(gè)層級(jí)單獨(dú)處理高很多,推薦大家嘗試使用粥诫。
層級(jí)拼接的處理主要在文章3.3油航、3.5、3.6部分怀浆,結(jié)合代碼和輸出結(jié)果谊囚,希望讀者能夠掌握這樣的處理方法。
1. 層級(jí)處理介紹
看過我前面介紹受試者處置頻數(shù)匯總的讀者执赡,應(yīng)該有印象镰踏。頻數(shù)匯總中,各條目對(duì)應(yīng)不同的變量條件的情況沙合,是很常見的奠伪。對(duì)應(yīng)的處理方法,無外乎單條目條件處理后匯總首懈,或者各條目條件合并為一個(gè)變量控制绊率,統(tǒng)一處理。
具有層級(jí)關(guān)系的頻數(shù)表究履,跟之前介紹的匯總表有2點(diǎn)不同滤否。第一,層級(jí)關(guān)系的條目數(shù)量由具體數(shù)據(jù)確認(rèn)挎袜,沒有事先指定;第二肥惭,層級(jí)關(guān)系的條目需按所要求的順序排序盯仪。
基于此,將多層級(jí)轉(zhuǎn)化為單層級(jí)時(shí)蜜葱,需要保留各層級(jí)信息全景,方便后續(xù)排序。
臨床試驗(yàn)TFL中牵囤,常見的具有層級(jí)關(guān)系的內(nèi)容有爸黄,地區(qū)國(guó)家滞伟、AE SOCPT的頻數(shù)匯總。
這篇介紹炕贵,國(guó)家地區(qū)匯總表的層級(jí)拼接處理梆奈,后續(xù)介紹AE SOCPT的層級(jí)處理。
2. 具體示例
這是一個(gè)涉及多個(gè)地區(qū)称开、國(guó)家的多中心1期試驗(yàn)亩钟,這張Table需要匯總Region、Country鳖轰、Site的信息清酥。
這些信息保存在ADSL中,Site信息由兩個(gè)變量拼接而成蕴侣,這里看成一個(gè)變量進(jìn)行處理焰轻。
這三個(gè)變量中“范圍”最小的是Site,一個(gè)Site有對(duì)應(yīng)的Country昆雀,一個(gè)Country有對(duì)應(yīng)的Region辱志。一行記錄有對(duì)應(yīng)3個(gè)變量的信息,每個(gè)變量信息都會(huì)被計(jì)數(shù)忆肾,也就是說一行記錄會(huì)被計(jì)數(shù)3次荸频。
這樣的“重復(fù)計(jì)數(shù)”,可以通過兩種方式實(shí)現(xiàn):第一客冈,計(jì)數(shù)3次旭从,每次計(jì)數(shù)不同的變量;第二场仲,將記錄拆分成3條和悦,一次計(jì)數(shù)3個(gè)變量的信息。
層次拼接法渠缕,就是采取第二種方式鸽素,拆分時(shí),通過變量拼接亦鳞,保留對(duì)應(yīng)的層級(jí)關(guān)系馍忽。
3. SAS代碼演示
首先,附上我的QC“5段論”:
***1. Create formats for output;
***2. Get data for analysis;
***3. Calculate statistics;
***4. Create dataset for QC;
***5. Compare;
3.1 匯總組的設(shè)置
這是一個(gè)Ongoing的1期劑量擴(kuò)大試驗(yàn)燕差,計(jì)劃有6個(gè)試驗(yàn)組遭笋,目前數(shù)據(jù)中只有前4個(gè)試驗(yàn)組的信息。缺失組別的內(nèi)容徒探,我會(huì)使用Means過程步中的preloadfmt
選項(xiàng)補(bǔ)充缺失組別的信息瓦呼,具體參考SAS編程:頻數(shù)匯總時(shí)如何處理分析分組種類不全的情況?测暗。
Shell中要求這張Table有匯總組(Total)央串,這個(gè)我會(huì)采用Format過程步中multilabel
選項(xiàng)進(jìn)行實(shí)現(xiàn)磨澡,具體內(nèi)容可以參考SAS編程:生成Table時(shí),匯總組(Total)組如何處理质和?稳摄。
基于上面兩點(diǎn)考慮,部分Format可以這樣設(shè)置:
***1. Craete Formats for output;
proc format;
value trt01pn(notsorted multilabel)
1 = 1
2 = 2
3 = 3
4 = 4
5 = 5
6 = 6
1-6 = 99 /*For total*/
;
run;
3.2 計(jì)算BigN的人群獲取
***2. Get data for analysis;
**2,1 Get data for BigN;
data adsl;
set adam.adsl;
where fasfl = "Y";
*Flag for count;
flag = 1;
length site $50;
site = catx("/", siteidss, invnam);
run;
3.3 計(jì)算小n的人群獲取——層級(jí)拼接
**2.2 Get data for small n;
data adsl_n;
set adsl;
length cat $200;
cat = strip(geogr1); output;
cat = strip(geogr1)||"!"||strip(propcase(countryl)); output;
cat = strip(geogr1)||"!"||strip(propcase(countryl))||"!"||strip(site); output;
proc sort;
by cat;
run;
第2部分提到侦另,一條記錄的3類信息會(huì)被計(jì)數(shù) (Region秩命、Country、Site)褒傅,利用Output語(yǔ)句將1條記錄輸出為3條弃锐,每一條對(duì)應(yīng)需要計(jì)數(shù)的那一類信息。拆分時(shí)殿托,各變量以感嘆號(hào)!
分隔霹菊,這樣可以通過感嘆號(hào)的數(shù)目來判斷所屬具體層級(jí)。
排序變量是新建的cat
變量支竹,其實(shí)這就相當(dāng)于按照by geogr1 countryl site
進(jìn)行排序旋廷。因?yàn)锳DSL數(shù)據(jù)集本身是Subject Level,1個(gè)受試者1條記錄礼搁,所以計(jì)算頻率時(shí)饶碘,數(shù)據(jù)集是不需要去重的。
3.4 計(jì)算BigN
處理好分析數(shù)據(jù)后馒吴,BigN的計(jì)算與之前的文章一樣:
***3. Calculate statistics;
**3.1 Derive BigN and save them to macro vars;
proc means data =adsl nway completetypes;
format trt01pn trt01pn.;
class trt01pn / preloadfmt mlf order = data;
var flag;
output n = bign nmiss = nmiss out = BigN;
run;
data _null_;
set BigN;
call symputx("N_"||strip(trt01pn), put(bign,best.));
run;
data check_bign;
set sashelp.vmacro;
where index(name, "N_") and length(name)<=6;
keep name value;
run;
3.5 計(jì)算小n
小n的計(jì)算也與之前文章大體類似扎运,只是不需要為分析變量cat
提前設(shè)置Format。
**3.2 Calculate small n and percentage;
*Get small n;
proc means data = adsl_n nway completetypes;
format trt01pn trt01pn.;
class trt01pn / preloadfmt mlf order = data;
class cat;
var flag;
output n = count nmiss = nmiss out = count1;
run;
*Get percentage;
data count2;
merge count1 bign;
by trt01pn;
length freq $200;
if bign ne 0 then freq = strip(put(count,best.))||" ("||strip(put(count/bigN*100,8.1)) ||")";
else freq = "0 (-)";
proc sort;
by cat trt01pn;
run;
*Transpose results;
proc transpose data = count2 out = count3 prefix= trt_ ;
by cat;
var freq;
id trt01pn;
run;
百分比處理完畢后饮戳,下面要對(duì)第一列的內(nèi)容進(jìn)行處理豪治。計(jì)數(shù)時(shí),是按拼接后的變量信息計(jì)數(shù)扯罐。計(jì)數(shù)完畢后负拟,需要根據(jù)所在層級(jí)輸出第一列的內(nèi)容。而所在層級(jí)的判斷歹河,是通過所含感嘆號(hào)數(shù)量進(jìn)行標(biāo)記掩浙。
data final1;
set count3;
length c1 - c8 $200;
if count(cat, "!") = 0 then c1 = cat;
else if count(cat, "!") = 1 then c1 = scan(cat, 2, "!");
else if count(cat, "!") = 2 then c1 = scan(cat, 3, "!");
c2 = trt_1;
c3 = trt_2;
c4 = trt_3;
c5 = trt_4;
c6 = trt_5;
c7 = trt_6;
c8 = trt_99;
keep c:;
proc sort;
by cat;
run;
輸出結(jié)果如下,結(jié)果排序?yàn)楦鲗蛹?jí)字母排序秸歧,以下基本為完整的輸出內(nèi)容了厨姚。
3.6 按匯總列頻數(shù)降序排序
具有層次關(guān)系的頻數(shù)匯總表,如果結(jié)果按字符排序寥茫,上面輸出就是最后的結(jié)果遣蚀。
但這類表通常需要按匯總組的頻數(shù)降序排列矾麻,頻數(shù)相同纱耻,按字符順序排序芭梯。這時(shí)候還需要對(duì)數(shù)據(jù)集進(jìn)一步處理,以達(dá)到排序的要求弄喘。
這一步玖喘,主要操作是為每一個(gè)層級(jí)附上對(duì)應(yīng)的匯總列頻數(shù),通過BY語(yǔ)句蘑志、Retain語(yǔ)句為組內(nèi)賦值實(shí)現(xiàn)累奈。
為3個(gè)層級(jí)新建對(duì)應(yīng)的分組變量 (cat1, cat2, cat3),并按層級(jí)分組排序:
*Create group vars;
data final1;
set count3;
length c1 - c8 $200;
if count(cat, "!") = 0 then c1 = cat;
else if count(cat, "!") = 1 then c1 = scan(cat, 2, "!");
else if count(cat, "!") = 2 then c1 = scan(cat, 3, "!");
c2 = trt_1;
c3 = trt_2;
c4 = trt_3;
c5 = trt_4;
c6 = trt_5;
c7 = trt_6;
c8 = trt_99;
*For freqency sort;
num = input(scan(c8,1,"("), best.);
cat1 = scan(cat, 1, "!");
cat2 = scan(cat, 2, "!");
cat3 = scan(cat, 3, "!");
keep num c:;
proc sort;
by cat1 cat2 cat3;
run;
為每一分組賦上組內(nèi)匯總頻數(shù) (cat1n, cat2n, cat3n)急但,并以頻數(shù)降序澎媒、相同頻數(shù)以字母順序升序排列:
*Get counts for the group vars;
data final2;
set final1;
by cat1 cat2 cat3;
retain cat1n cat2n cat3n;
if first.cat1 then cat1n = num;
if first.cat2 then cat2n = num;
if first.cat3 then cat3n = num;
proc sort;
by descending cat1n cat1 descending cat2n cat2 descending cat3n cat3;
run;
輸出結(jié)果如下:
這個(gè)就是最后輸出結(jié)果的主體部分,結(jié)合cat1n, cat2n, cat3n的具體取值波桩,希望讀者能夠掌握頻數(shù)倒序排序的處理戒努。
4. 主體程序代碼匯總:
***1. Craete Formats for output;
proc format;
value trt01pn(notsorted multilabel)
1 = 1
2 = 2
3 = 3
4 = 4
5 = 5
6 = 6
1-6 = 99 /*For total*/
;
run;
***2. Get data for analysis;
**2,1 Get data for BigN;
data adsl;
set adam.adsl;
where fasfl = "Y";
*Flag for count;
flag = 1;
length site $50;
site = catx("/", siteidss, invnam);
run;
**2.2 Get data for small n;
data adsl_n;
set adsl;
length cat $200;
cat = strip(geogr1); output;
cat = strip(geogr1)||"!"||strip(propcase(countryl)); output;
cat = strip(geogr1)||"!"||strip(propcase(countryl))||"!"||strip(site); output;
proc sort;
by cat;
run;
***3. Calculate statistics;
**3.1 Derive BigN and save them to macro vars;
proc means data =adsl nway completetypes;
format trt01pn trt01pn.;
class trt01pn / preloadfmt mlf order = data;
var flag;
output n = bign nmiss = nmiss out = BigN;
run;
data _null_;
set BigN;
call symputx("N_"||strip(trt01pn), put(bign,best.));
run;
data check_bign;
set sashelp.vmacro;
where index(name, "N_") and length(name)<=6;
keep name value;
run;
**3.2 Calculate small n and percentage;
*Get small n;
proc means data = adsl_n nway completetypes;
format trt01pn trt01pn.;
class trt01pn / preloadfmt mlf order = data;
class cat;
var flag;
output n = count nmiss = nmiss out = count1;
run;
*Get percentage;
data count2;
merge count1 bign;
by trt01pn;
length freq $200;
if bign ne 0 then freq = strip(put(count,best.))||" ("||strip(put(count/bigN*100,8.1)) ||")";
else freq = "0 (-)";
proc sort;
by cat trt01pn;
run;
*Transpose results;
proc transpose data = count2 out = count3 prefix= trt_ ;
by cat;
var freq;
id trt01pn;
run;
*Create group vars;
data final1;
set count3;
length c1 - c8 $200;
if count(cat, "!") = 0 then c1 = cat;
else if count(cat, "!") = 1 then c1 = scan(cat, 2, "!");
else if count(cat, "!") = 2 then c1 = scan(cat, 3, "!");
c2 = trt_1;
c3 = trt_2;
c4 = trt_3;
c5 = trt_4;
c6 = trt_5;
c7 = trt_6;
c8 = trt_99;
*For freqency sort;
num = input(scan(c8,1,"("), best.);
cat1 = scan(cat, 1, "!");
cat2 = scan(cat, 2, "!");
cat3 = scan(cat, 3, "!");
keep num c:;
proc sort;
by cat1 cat2 cat3;
run;
*Get counts for the group vars;
data final2;
set final1;
by cat1 cat2 cat3;
retain cat1n cat2n cat3n;
if first.cat1 then cat1n = num;
if first.cat2 then cat2n = num;
if first.cat3 then cat3n = num;
proc sort;
by descending cat1n cat1 descending cat2n cat2 descending cat3n cat3;
run;
***4. Create dataset for QC;
略
***5. Compare;
略
總結(jié)
這篇文章介紹了處理層級(jí)關(guān)系頻數(shù)表的方法——層級(jí)拼接法。這個(gè)方法的效率比常規(guī)各層級(jí)單獨(dú)處理要高很多镐躲,推薦大家使用储玫。
這類表格的排序,可能按字母順序進(jìn)行排序萤皂,也可能按匯總組頻數(shù)倒序排列撒穷。文章也介紹了這兩種排序的處理。
SAS編程-Table:層級(jí)拼接法輸出AE SOC裆熙、PT的受試者發(fā)生率介紹了端礼,關(guān)于AE SOC、PT層級(jí)關(guān)系嵌套的處理弛车。SOC和PT是兩層嵌套齐媒,處理上比Region、Country纷跛、Site 3層嵌套要簡(jiǎn)單點(diǎn)喻括。
感謝閱讀, 歡迎關(guān)注贫奠!
若有疑問唬血,歡迎評(píng)論交流!