参考资料:《Amazing Graph Series: Butterfly Graph Using SGPLOT and GTL》,可以在www.pharmasug.org网站上下载。
摸鱼时看到一篇关于蝴蝶图的文章,跟着写一遍顺便纪录下来,数据集会附在最后。
** options set **;
ods escapechar="^";
ods _all_ close;
options ls=max;
** create template **;
proc template;
define statgraph fly;
begingraph;
entrytitle "Summary of Most Frequent TEAEs (>=10% of Total) by Treatment and Toxicity Grade";
entryfootnote halign=right "Data Extraction Date: &sysdate.T&systime.";
** 定义图例的颜色以及对应的变量 **;
discreteattrmap name="name";
value "Grade 1" / fillattrs=(color=CADETBLUE);
value "Grade 2" / fillattrs=(color=bib);
value "Grade 3" / fillattrs=(color=red);
value "Grade 4" / fillattrs=(color=purple);
enddiscreteattrmap;
discreteattrvar attrvar=MYID_GRD var=grade attrmap="name";
** 定义布局,为左中右式布局 **;
layout lattice / rowdatarange= union columnweights= (0.42 0.16 0.42) columns=3;
** 定义左侧 **;
layout overlay / walldisplay=none
** 定义X轴范围 网格线 Y轴不显示**;
xaxisopts=(tickvalueattrs=(size=7)
display=(line tickvalues) griddisplay=on
reverse=true linearopts=(viewmin=0 viewmax=70
tickvaluesequence=(start=0 end=70 increment=10)))
yaxisopts=(display=none reverse=true);
** 定义柱子属性 **;
barchart category=aedecod response=_1/
group=myid_grd name="bar1"
orient=horizontal dataskin=pressed segmentlabel=true segmentlabelattrs=(color=white);
entry "Treatment 1 (N=&n1.)" / autoalign=(bottomleft);
endlayout;
** 定义中间部分 **;
layout overlay / xaxisopts=(display=none) walldisplay=none yaxisopts=(display=(tickvalues)
tickvaluehalign=center);
barchart category=aedecod response=_1/ orient=horizontal datatransparency=1;
endlayout;
** 定义右侧 **;
layout overlay / walldisplay=none xaxisopts=(tickvalueattrs=(size=7) display=(line tickvalues)
griddisplay=on linearopts=(viewmin=0 viewmax=70 tickvaluesequence=(start=0 end=70 increment=10)))
yaxisopts=(display=none reverse=true);
barchart category=aedecod response=_2/
group=MYID_GRD orient=horizontal dataskin=pressed segmentlabel=true
segmentlabelattrs=(color=white);
entry "Treatment 2 (N=&n2.)" / autoalign=(bottomright);
endlayout;
** 定义底部属性,sidebar可以用来放置附加信息,比如图例相关信息 **;
sidebar / align=bottom;
discretelegend "bar1" / across=1 halign=center title="Patients (%)"
itemsize=(fillheight=10px fillaspectratio=golden) border=false;
endsidebar;
endlayout;
endgraph;
end;
run;
** 输出文件 **;
ods listing gpath="pathname";
ods graphics on/ reset imagename="f_butterfly" outputfmt=png width=1100px height=700px noborder;
proc sgrender data=fin template=fly;
run;
ods html close;
ods listing;
** dummy data **;
data adae;
infile datalines delimiter = ',';
input usubjid :$18. trta $ trtan aedecod :$200. aetoxgrn ;
datalines;
PHARM-ABC-100-0005, TRT A, 1, Bloating, 1
PHARM-ABC-100-0005, TRT A, 1, Chills, 1
PHARM-ABC-100-0005, TRT A, 1, Myalgia, 1
PHARM-ABC-100-0005, TRT A, 1, Sinus tachycardia, 2
PHARM-ABC-100-0005, TRT A, 1, Nausea, 3
PHARM-ABC-101-0005, TRT A, 1, Hypotension, 3
PHARM-ABC-101-0004, TRT A, 1, Bloating, 1
PHARM-ABC-101-0004, TRT A, 1, Chills, 2
PHARM-ABC-101-0004, TRT A, 1, Blood lactic acid increased, 1
PHARM-ABC-101-0004, TRT A, 1, Diarrhoea, 1
PHARM-ABC-101-0004, TRT A, 1, Hypoglycaemia, 1
PHARM-ABC-101-0004, TRT A, 1, Hypomagnesaemia, 1
PHARM-ABC-101-0004, TRT A, 1, Hypotension, 2
PHARM-ABC-101-0004, TRT A, 1, Hypoxia, 2
PHARM-ABC-101-0004, TRT A, 1, Nausea, 1
PHARM-ABC-101-0004, TRT A, 1, Pollakiuria, 1
PHARM-ABC-101-0004, TRT A, 1, Skin infection, 2
PHARM-ABC-101-0004, TRT A, 1, Thrombocytopenia, 2
PHARM-ABC-101-0005, TRT A, 1, Arthralgia, 1
PHARM-ABC-101-0005, TRT A, 1, Back pain, 1
PHARM-ABC-101-0005, TRT A, 1, Bloating, 1
PHARM-ABC-101-0005, TRT A, 1, Cough, 1
PHARM-ABC-101-0005, TRT A, 1, Dyspnoea exertional, 1
PHARM-ABC-101-0005, TRT A, 1, Fatigue, 1
PHARM-ABC-101-0005, TRT A, 1, Nausea, 1
PHARM-ABC-101-0005, TRT A, 1, Oropharyngeal pain, 1
PHARM-ABC-101-0005, TRT A, 1, Tachycardia, 1
PHARM-ABC-101-0006, TRT A, 1, Bloating, 2
PHARM-ABC-101-0006, TRT A, 1, Hypotension, 2
PHARM-ABC-101-0006, TRT B, 2, Hypoxia, 2
PHARM-ABC-101-0006, TRT B, 2, Nausea, 1
PHARM-ABC-101-0006, TRT B, 2, Pleural effusion, 2
PHARM-ABC-101-0006, TRT B, 2, Tachycardia, 2
PHARM-ABC-101-0006, TRT B, 2, Thrombocytopenia, 1
PHARM-ABC-102-0004, TRT B, 2, Abdominal pain upper, 3
PHARM-ABC-102-0004, TRT B, 2, Cough, 1
PHARM-ABC-102-0004, TRT B, 2, Hypoxia, 1
PHARM-ABC-102-0004, TRT B, 2, Nausea, 1
PHARM-ABC-102-0004, TRT B, 2, Pulmonary embolism, 2
PHARM-ABC-102-0004, TRT B, 2, Skin laceration, 1
PHARM-ABC-102-0005, TRT B, 2, Abdominal discomfort, 1
PHARM-ABC-102-0005, TRT B, 2, Adrenal insufficiency, 2
PHARM-ABC-102-0005, TRT B, 2, Arthralgia, 2
PHARM-ABC-102-0005, TRT B, 2, Bloating, 1
PHARM-ABC-102-0005, TRT B, 2, Chest discomfort, 1
PHARM-ABC-102-0005, TRT B, 2, Chills, 2
PHARM-ABC-102-0005, TRT B, 2, Decreased appetite, 1
PHARM-ABC-102-0005, TRT B, 2, Fatigue, 2
PHARM-ABC-102-0005, TRT B, 2, Hepatitis, 1
PHARM-ABC-102-0005, TRT B, 2, Hypoxia, 1
PHARM-ABC-102-0005, TRT B, 2, Myalgia, 1
PHARM-ABC-102-0005, TRT B, 2, Pain in extremity, 1
PHARM-ABC-102-0005, TRT B, 2, Skin mass, 1
;
run;
** Add Total Treatment group **;
data adae1;
set adae;
output;
trtan = 99;
trta = 'Total';
output;
run;
** Count Bign **;
proc sql noprint;
select count(distinct usubjid) into :n1 trimmed from adae1 where trtan=1;
select count(distinct usubjid) into :n2 trimmed from adae1 where trtan=2;
select count(distinct usubjid) into :n3 trimmed from adae1 where trtan=99;
quit;
proc sort data = adae1(where=(aedecod ne ""));
by trtan usubjid aedecod descending aetoxgrn;
run;
data ae_max;
set adae1;
by trtan usubjid aedecod descending aetoxgrn;
if first.aedecod;
run;
proc freq data=ae_max noprint;
table aedecod*trtan*aetoxgrn/out=freq1(drop=percent);
run;
proc freq data=ae_max noprint;
table aedecod*trtan/out=freq2(drop=percent);
run;
proc transpose data=freq2 out=freq3 prefix=_;
by aedecod;
id trtan;
var count;
run;
data temp1;
set freq1;
if trtan=1 then perc=input(put((count / &n1)*100,5.),8.);
if trtan=2 then perc=input(put((count / &n2)*100,5.),8.);
if trtan=99 then perc=input(put((count / &n3)*100,5.),8.);
run;
proc sort data=temp1;
by aedecod aetoxgrn trtan;
run;
proc transpose data = temp1 out = temp2 (drop = _name_) prefix=_;
by aedecod aetoxgrn;
id trtan;
var perc;
run;
data temp2;
set temp2;
if _1=. then _1=0;
if _2=. then _2=0;
proc sort;
by aedecod;
run;
data temp3;
set freq3;
perc99=input(put((_99 / &n3)*100,5.),8.);
keep aedecod perc99;
proc sort;
by aedecod;
run;
data fin;
merge temp2 temp3;
by aedecod;
if perc99>=10;
grade="Grade "||strip(put(aetoxgrn,8.));
tox=put(aetoxgrn,best.);
/* _1=-_1;*/
label
aedecod = "Preferred Term"
_1= "Percent Subjects Trt A"
_2= "Percent Subjects Trt B"
perc99= "Percent Subjects Total";
proc sort;
by descending perc99;
run;