Friday, May 11, 2012

Adverse Event Tables (Continued)

I stated in my previous post that I would share a few more examples on how to use the AESUM macro.  Well, I like to keep my promises, so here we go...


To review, I am taking this data from Jack Shostack's book SAS Programming in the Pharmaceutical Industry.  The data can be found here.  (Scroll down to Program 5.4.)



/***  INPUT SAMPLE TREATMENT DATA  ***/
data treat;
label subjid = "Subject Number"
      trtcd  = "Treatment";     
input subjid trtcd @@;
datalines;
101 1  102 0  103 0  104 1  105 0  106 0  107 1  108 1  109 0  110 1
111 0  112 0  113 0  114 1  115 0  116 1  117 0  118 1  119 1  120 1
121 1  122 0  123 1  124 0  125 1  126 1  127 0  128 1  129 1  130 1
131 1  132 0  133 1  134 0  135 1  136 1  137 0  138 1  139 1  140 1
141 1  142 0  143 1  144 0  145 1  146 1  147 0  148 1  149 1  150 1
151 1  152 0  153 1  154 0  155 1  156 1  157 0  158 1  159 1  160 1
161 1  162 0  163 1  164 0  165 1  166 1  167 0  168 1  169 1  170 1
;
run;

/***  INPUT SAMPLE ADVERSE EVENT DATA  ***/
data ae;
label subjid   = "Subject Number"
      aebodsys = "Body System of Event"
      aedecod  = "Preferred Term for Event"
      aerel    = "Relatedness: 1=not,2=possibly,3=probably"
      aesev    = "Severity/Intensity:1=mild,2=moderate,3=severe";     
input subjid 1-3 aerel 5 aesev 7 aebodsys $ 9-34 aedecod $ 38-62;
datalines;
101 1 1 Cardiac disorders            Atrial flutter
101 2 1 Gastrointestinal disorders   Constipation
102 2 2 Cardiac disorders            Cardiac failure
102 1 1 Psychiatric disorders        Delirium
103 1 1 Cardiac disorders            Palpitations
103 1 2 Cardiac disorders            Palpitations
103 2 2 Cardiac disorders            Tachycardia
115 3 2 Gastrointestinal disorders   Abdominal pain
115 3 1 Gastrointestinal disorders   Anal ulcer
116 2 1 Gastrointestinal disorders   Constipation
117 2 2 Gastrointestinal disorders   Dyspepsia
118 3 3 Gastrointestinal disorders   Flatulence
119 1 3 Gastrointestinal disorders   Hiatus hernia
130 1 1 Nervous system disorders     Convulsion
131 2 2 Nervous system disorders     Dizziness
132 1 1 Nervous system disorders     Essential tremor
135 1 3 Psychiatric disorders        Confusional state
140 1 1 Psychiatric disorders        Delirium
140 2 1 Psychiatric disorders        Sleep disorder
141 1 3 Cardiac disorders            Palpitations
;
run;


Although the macro requires two separate datasets, I am going to merge the two because I need the treatment group variable in the AEDSN dataset for grouping in the BYVAR parameter.  But I still need both datasets for the macro input.

data ae;
      merge ae treat;
      by subjid;
run;


/***  Call the AESUM macro  ***/
/***  (remember to either call the full code from your SAS editor or to save it in a separate file as I did below)  ***/
%inc 'D:\Documents and Settings\dbateman\Desktop\Reusable Macros\AE Summary Macro.sas';

/***  I added the BYVAR parameter to group by TRTCD  ***/
/***  I added the WHR parameter to select only drug-related AEs  ***/
/***  I changed the DISPLAYSOC parameter to N  ***/
%aesum(aedsn=ae, whr=%str(aerel in (2,3)), safdsn=treat, byvar=trtcd, grdvar=aesev, soc=aebodsys, pref=aedecod, subjid=subjid, minpercent=-1, outdsn=aesum, displaysoc=N);

After running the AESUM macro, this is what the OUTDSN table holds:



With the data in this form, there are a couple of things you can do:
  1. You can run two separate outputs and 
    • only output any by0_ variables for the control group
    • only output any by1_ variables for the treatment group
  2. You can run a single output with just the _grd0 (all grades combined) variables or just the Grade 3-4, or whatever you desire as your situation allows
I will do both, just for fun.




SAS Code 1


options formchar="|____|+|___+=|_/\<>*" pageno=1 nonumber nodate orientation=portrait center;
ods listing close;
ods rtf file="D:\Documents and Settings\dbateman\Desktop\AE Table.rtf" style=journal;
ods escapechar='~';

%let user=%sysfunc(upcase(&sysuserid.));
%let proddt=%sysfunc(date(),worddate.);

title1 j=left font='Arial' 'ABC Company, Inc.' j=right "Page ~{pageof}";
title2 j=left font='Arial' "Protocol: AZ1234";
footnote1 j=left font='Arial' "Program: AE_Example.sas by &user." j=right "Date Produced: &proddt.";
proc report data=aesum nowindows split='^' style(column)={asis=on}
            style(report)={font=('Arial',9.5pt,bold italic) pretext="Drug-Related Treatment Emergent Adverse Events \line\ (Control Group)"};
      column header by0_grd0 by0_grd1 by0_grd2 by0_grd3 aedecod;
      define header / display left 'System Organ Class/^Preferred Term' style=[CellWidth=30%];
      define by0_grd0 / display center 'All Grades^n (%)' style=[CellWidth=10%];
      define by0_grd1 / display center 'Mild^n (%)' style=[CellWidth=10%];
      define by0_grd2 / display center 'Moderate^n (%)' style=[CellWidth=10%];
      define by0_grd3 / display center 'Severe^n (%)' style=[CellWidth=10%];
      define aedecod / noprint;  /*  Must include this in order to identify correct rows to bold in next step  */
      compute aedecod;
        if aedecod=' ' then do/*  If system organ class is listed, then bold that row  */
           call define(_row_, "style", "style=[font_weight=bold]");
        end;
      endcomp;
run;

proc report data=aesum nowindows split='^' style(column)={asis=on}
            style(report)={font=('Arial',9.5pt,bold italic) pretext="Drug-Related Treatment Emergent Adverse Events \line\ (Treatment Group)"};
      column header by1_grd0 by1_grd1 by1_grd2 by1_grd3 aedecod;
      define header / display left 'System Organ Class/^Preferred Term' style=[CellWidth=30%];
      define by1_grd0 / display center 'All Grades^n (%)' style=[CellWidth=10%];
      define by1_grd1 / display center 'Mild^n (%)' style=[CellWidth=10%];
      define by1_grd2 / display center 'Moderate^n (%)' style=[CellWidth=10%];
      define by1_grd3 / display center 'Severe^n (%)' style=[CellWidth=10%];
      define aedecod / noprint;  /*  Must include this in order to identify correct rows to bold in next step  */
      compute aedecod;
        if aedecod=' ' then do/*  If system organ class is listed, then bold that row  */
           call define(_row_, "style", "style=[font_weight=bold]");
        end;
      endcomp;
run;

ods rtf close;
ods listing;
title; footnote;


Output 1






SAS Code 2


options formchar="|____|+|___+=|_/\<>*" pageno=1 nonumber nodate orientation=portrait center;
ods listing close;
ods rtf file="D:\Documents and Settings\dbateman\Desktop\AE Table.rtf" style=journal;
ods escapechar='~';

%let user=%sysfunc(upcase(&sysuserid.));
%let proddt=%sysfunc(date(),worddate.);

title1 j=left font='Arial' 'ABC Company, Inc.' j=right "Page ~{pageof}";
title2 j=left font='Arial' "Protocol: AZ1234";
footnote1 j=left font='Arial' "Program: AE_Example.sas by &user." j=right "Date Produced: &proddt.";
proc report data=aesum nowindows split='^' style(column)={asis=on}
            style(report)={font=('Arial',9.5pt,bold italic) pretext="Drug-Related Treatment Emergent Adverse Events \line\ (By Treatment Group)"};
      column header by0_grd0 by1_grd0 aedecod;
      define header / display left 'System Organ Class/^Preferred Term' style=[CellWidth=30%];
      define by0_grd0 / display center 'Control Group^n (%)' style=[CellWidth=10%];
      define by1_grd0 / display center 'Treatment Group^n (%)' style=[CellWidth=10%];
      define aedecod / noprint;  /*  Must include this in order to identify correct rows to bold in next step  */
      compute aedecod;
        if aedecod=' ' then do;  /*  If system organ class is listed, then bold that row  */
           call define(_row_, "style""style=[font_weight=bold]");
        end;
      endcomp;
run;

ods rtf close;
ods listing;
titlefootnote;


Output 2

You can see that this output simply takes the first column ("All Grades") from each of the two outputs above and merges them together:




There are many more options with this macro.  Take time to play around with it and see how it can fit your needs.  And, please, if you find any errors in this macro as you go along, leave me a comment so I can continue to make this macro more user friendly!

18 comments:

Anonymous said...

Your means of telling everything in this post is in fact good, every one be capable of easily be aware of it, Thanks a lot.



Feel free to surf to my blog ... Cheap Louis Vuitton Bags

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

There's certainly a lot to learn about this topic. I love all of the points you've made.


My blog; Wholesale Jerseys

Anonymous said...

Asking questions are in fact nice thing if you are not understanding something totally, but this paragraph offers nice understanding yet.


My homepage - Michael Kors Handbags

Anonymous said...

I'm gone to say to my little brother, that he should also pay a quick visit this weblog on regular basis to obtain updated from most up-to-date gossip.

Feel free to surf to my web blog: This Site

Anonymous said...

Wonderful post however , I was wondering if you could write a litte more on this topic?
I'd be very grateful if you could elaborate a little bit further. Bless you!

Here is my blog; More hints

Anonymous said...

Thanks , I have recently been searching for information about this topic for ages and yours is the greatest I have discovered so
far. But, what about the conclusion? Are you positive concerning the source?


my site More Help

Anonymous said...

Really no matter if someone doesn't know after that its up to other users that they will assist, so here it happens.

Feel free to visit my web site ... helpful Resources

Anonymous said...

Hi there mates, its great piece of writing about tutoringand
completely explained, keep it up all the time.

Also visit my site Kobe Bryant Shoes

Anonymous said...

Hi, this weekend is nice in support of me, for the reason that
this moment i am reading this enormous educational paragraph here at my house.



Look at my website - Nike Trainers

Anonymous said...

Very good info. Lucky me I ran across your blog by accident (stumbleupon).
I've book-marked it for later!

My blog ... Mulberry UK

Anonymous said...

That is very fascinating, You are an overly skilled blogger.
I've joined your rss feed and look ahead to in the hunt for more of your magnificent post. Additionally, I have shared your site in my social networks

My web page Officiel Louis Vuitton Site

Anonymous said...

Hello there, just became alert to your blog through Google, and
found that it's truly informative. I am going to watch out for brussels. I'll be grateful if you continue this in future.
A lot of people will be benefited from your writing.
Cheers!

Feel free to surf to my web blog :: Chaussure De Foot Pas Cher

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

An excellent example for AE safety tables. This is helpful to everyone who are working as SAS programmer in clinical domain. Thanks a ton!!!!

Unknown said...

Thanks for sharing the useful SAS programming with output, SAS is the recent technology, you must learn this valuable course to get future in IT firm.

Jozef said...

Thank you very much for providing this code explaining the involved steps. I was wondering whether you could also post a code on calculating p-values for between the group differences for each SOC and PT? Thanks