Patient Profile Graphs using SAS Sanjay Matange, SAS Institute, Inc.
Before We Get Started Let us do a quick show of hands. How many users of SAS 9.2? How many using SAS 9.3? How many have heard of ODS Graphics? How many users of SG Procedures How many users of GTL? How many export data to other software for graphics? Has anyone heard of ODS Graphics Designer?
Disclaimer I am not a Statistician or a Bio-Statistician. I do not have actual domain knowledge in health care. I am just The Graph Guy from SAS. This presentation is based on my understanding of Patient Profile Graphs as learned from users like you. If you find any incorrect terminology, please feel free to tell me (after the presentation). My goal is to: Show you some new graphics features in SAS. To better understand your needs for graphics, so I can ensure SAS software is meeting your needs.
Patient profile reports Provide detailed information on a specific subject in the study. Includes relevant data such as: Adverse events. Concomitant medications. Vital statistics. This report may be in narrative form or visual report. 4
Visual Patient Profiles This presentation covers the creation of graphs that are useful for inclusion in visual patient profiles. The graphs included in this presentation are: Adverse event timeline graph. Concomitant medications graph. Vital statistics graph. Lab values graph. Summary of prescribed medications graph. 5
Data The data for these graph comes from the following CDISC STDM domains: AE CM VS LB 6
Statistical Graphics Procedures We will use the SG Procedures to create these graphs. Use the SGPLOT procedure for single cell graphs. Use the SGPANEL procedure for classification panel graphs. 7
The SGPLOT Procedure To create the AE and CM graphs, we will use the SGPLOT procedure. The SAS 9.3 release of SGPLOT procedure includes a new plot type called the HIGHLOW plot. The HIGHLOW Bar plot is particularly suitable to create many of these graphs because: It plots a floating bar segment. It displays a label at the low and/or high end of the bar. It can display an arrowhead at either end of the bar. While I will use SAS9.3 to create these graphs, you can create these with SAS 9.2, with some extra coding. 8
HIGHLOW Plot with Type=Bar title 'Vehicle Mileage Ranges by Type'; proc sgplot data=carstats(where=(type ne 'Hybrid')); highlow y=type low=meancity high=meanhwy / type=bar lowlabel=meancity highlabel=meanhwy; yaxis display=(nolabel); xaxis label='mileage'; run; 9
AE Graph Data Let us make the AE timeline graph. Here are the relevant columns from the AE data set that we will use to create the graph. Note this extra column. 10
AE Timeline Graph - 1 title "Adverse Events for Patient Id = &pid (SAS 9.3)"; proc sgplot data=ae_cap2; format aestdate date7.; refline 0 / axis=x lineattrs=(color=black); highlow y=aeseq low=aestdy high=aeendy / type=bar group=aesev lineattrs=(color=black pattern=solid) barwidth=0.8 lowlabel=aedecod highcap=aehicap; xaxis grid display=(nolabel); yaxis grid display=(noticks novalues nolabel); run; 11
AE Timeline Graph - 1 Here are some features of this graph: A bar segment is shown for each AE from start to end. AE name is shown at the lower end of the bar segment. AE names are displayed near the bar instead of the Y axis. Study days are shown on the x axis. 12
AE Timeline Graph - 1 Here are some shortcomings of this graph: We want to include all possible severities in the legend in the correct order. The default group colors are used for the two severity values. Study days are shown on the x axis, but no dates are shown. 13
AE Timeline Graph - 2 To include all possible severity values in the legend I added dummy values to data set. Here I have added 3 dummy values to the data set, one for each value of severity expected. The start and end day values are set to missing. 14
AE Timeline Graph - 2 title "Adverse Events for Patient Id = &pid (SAS 9.3)"; proc sgplot data=ae_cap_dummy; format aestdate date7.; refline 0 / axis=x lineattrs=(color=black); highlow y=aeseq low=aestdy high=aeendy / type=bar group=aesev lineattrs=(color=black pattern=solid) barwidth=0.8 lowlabel=aedecod highcap=aehicap; xaxis grid display=(nolabel); yaxis grid display=(noticks novalues nolabel); run; 15
AE Timeline Graph - 2 Here are the features of this graph: Now, all the severity values are shown in the legend in the correct sequence. However, the colors for each severity are not what we want. 16
About Group Attributes Normally, group colors are assigned to group values in the order of the values in the data. Group assignments can change every time you create a graph based on the order of the group values in the data. However, often we want specific group attributes for specific group values. The Discrete Attributes Map feature, added with SAS 9.3 allows us to do this.
Attribute Maps You can define a discrete attributes map with specific values for color, symbol and line patterns by value. This is similar to the format procedure. Then, whenever a group value is encountered, its attributes are derived from the map. For SG procedures, this map can be defined as a data set. For GTL, this attributes map can be defined inline in the code. In GTL, the legend can get the values from the attributes map. This feature is not yet implemented in SG. GTL also supports Range Attributes Map.
AE Timeline Graph - 3 We want to use specific colors (green, yellow, red) each of the severity values. (mild, moderate, severe). To do this, we define a discrete attributes map data set, to be used by the procedure and plot statement. The map id is Severity and color values for each group value are defined as shades of green, yellow and red. 19
AE Timeline Graph - 3 title "Adverse Events for Patient Id = &pid (SAS 9.3)"; proc sgplot data=ae_cap_dummy dattrmap=attrmap; format aestdate date7.; refline 0 / axis=x lineattrs=(color=black); highlow y=aeseq low=aestdy high=aeendy / type=bar group=aesev lineattrs=(color=black pattern=solid) attrid=severity barwidth=0.8 lowlabel=aedecod highcap=aehicap; xaxis grid display=(nolabel); yaxis grid display=(noticks novalues nolabel); run; 20
Controlling the Legend Now we have the correct colors in the legend for the three severity values. The three dummy values, one for each severity ensure all the severity levels are displayed even if they are not present. In GTL, you don t need to do this, as you can get the group values defined in the attribute map. 21
Arrowheads Note the arrowheads for some of the events. In this graph, we show the highcap for the event if its end date is missing. The same is done for the low cap. The idea is that you can use these caps to indicate events that run past the study dates. 22
AE Timeline Graph - 4 We want to add a second horizontal axis displaying the study dates. To do this, we will add a scatter plot with X=aestdate, associated with the top X2 axis. Nothing will be plotted as we will set the marker size to zero. But, the result is that a second X2 date axis will be displayed. We will use macro variables to synchronize the extents of the X and X2 axis so they match up.
AE Timeline Graph - 4 title "Adverse Events for Patient Id = &pid (SAS 9.3)"; proc sgplot data=ae_cap_dummy dattrmap=attrmap; format aestdate date7.; refline 0 / axis=x lineattrs=(color=black); highlow y=aeseq low=aestdy high=aeendy / type=bar group=aesev l ineattrs=(color=black pattern=solid) barwidth=0.8 lowlabel=aedecod highcap=aehicap attrid=severity; scatter y=aeseq x=aestdate / x2axis markerattrs=(size=0); xaxis grid display=(nolabel) offsetmax=0.02 values=(&minday2 to &maxday by 2); x2axis display=(nolabel) offsetmax=0.02 values=(&mindate2 to &maxdate); yaxis grid display=(noticks novalues nolabel); run; 24
AE Timeline Graph Now it looks like we are getting what we want. Except for the duplicate entries in the data. 25
AE Timeline by Name We exclude any duplicate AE names with same severity and start date. Instead of drawing the graph by the event sequence, we ll draw it by event name. Here is our final AE timeline graph. SAS 9.3 AE Timeline 26
AE Timeline Graph using SAS 9.2 This graph can also be created using SAS 9.2 features with a little extra effort. See the blog article below for more information. SAS 9.2 AE Timeline 27
CM Meds Graph Data Now let us make the CM meds timeline graph. Here are the relevant columns from the CM data set that we will use to create the graph. We have created a combined medication name including a shortened dose label. 28
CM Timeline Graph - 1 title "Concomitant Medications for Patient Id = &pid (SAS 9.3)"; proc sgplot data=cmmeds noautolegend nocycleattrs; refline 0 / axis=x lineattrs=(thickness=1 color=black); highlow y=cmseq low=cmstdy high=cmendy / type=bar fillattrs=(color=cx9bdcf2) barwidth=0.8 lowcap=cmlocap highcap=cmhicap lowlabel=cmmed labelattrs=(size=7); scatter y=cmseq x=cmstdate / markerattrs=(size=0) x2axis; yaxis grid display=(nolabel noticks novalues) values=(0 to 7 by 1) min=0; xaxis grid label='study Days' offsetmax=0.02 values=(&minday2 to &maxday by 2); x2axis notimesplit display=(nolabel) offsetmax=0.02 tickvalueformat=date7. values=(&mindate2 to &maxdate); run; 29
CM Timeline Graph - 2 It would be nice if the occurrence of the adverse events can be displayed on the meds timeline. This data set includes three additional columns, each containing the day of each event type. 30
CM Timeline Graph - 2 title "Concomitant Medications for Patient Id = &pid (SAS 9.3)"; proc sgplot data=cmmeds noautolegend nocycleattrs; refline 0 / axis=x lineattrs=(thickness=1 color=black); refline mild / axis=x lineattrs=(pattern=solid thickness=2 color=cx00af00) name='mi' legendlabel='mild'; refline moderate / axis=x lineattrs=(pattern=solid thickness=2 color=cxcfaf00) name='mo' legendlabel='moderate'; refline severe / axis=x lineattrs=(pattern=solid thickness=2 color=cxaf0000) name='se' legendlabel='severe'; keylegend 'mi' 'mo' 'se' / title='severity'; highlow y=cmseq low=cmstdy high=cmendy / <options>; run; 31
AE Reference Lines Now, we have used three reference lines to draw the adverse events on this graph by severity. The severity level is displayed in the legend. 32
Synchronizing AE and CM Graphs Note: The x axes of the two graphs are not synchronized with each other. This is due to the combination of the event or medication name and the start date. So, while the reference lines do provide an indication for the start of each event, it would be nice to synchronize the x axis of the two graphs. 33
Synchronizing AE and CM Axes To synchronize the x axes of the two graphs, we have merged the AE and CM data into one data set. Then, we have rendered each graph again, with both AE and CM events, but one of them is set to transparency=1. Now, the axes are correctly aligned. 34
The SGPANEL Procedure For Vital Signs graph, we will use the SGPANEL procedure to create a panel classified by vital sign. Here is an example of a classification panel created by the SGPANEL procedure. title 'Vehicle Mileage by Type...'; proc sgpanel data=sashelp.cars (where=(type ne 'Hybrid')); format mpg_city 4.1; panelby origin / layout=rowlattice novarname; hbar type / response=mpg_city stat=mean group=type dataskin=gloss; rowaxis display=(nolabel); colaxis label='mileage'; run; 35
Vital Statistics Graph Data Here are the relevant columns from the VS data set that we will use to create the graph. We will use id as the class variable. We will also use the AE reference lines. X, High and Low columns are used to draw the bands. 36
Vital Statistics Panel 37
Vital Statistics Panel This graph shows plots for three vital statistics over time. The normal limits for each statistic is shown as a band. AE event reference lines are shown. The VS name is shown in the row header on the right, and also as an inset for ease of readability. Two legends are shown, one for the type (lying down, etc.), and one for the AE event severity. 38
Code for VS Plot title "Vital Statistics for Patient Id = &pid"; proc sgpanel data=vs_with_events noautolegend nocycleattrs; panelby id / onepanel layout=rowlattice uniscale=column novarname spacing=10; band x=x lower=low upper=high / transparency=0.6 fill nooutline fillattrs=(color=lightblue); refline 0 / axis=x lineattrs=(thickness=1 color=black); refline mild / axis=x lineattrs=(thickness=2 color=cx00af00) name='mi legendlabel='mild'; refline moderate / axis=x lineattrs=(thickness=2 color=cxcfaf00) name='mo' legendlabel='moderate'; refline severe / axis=x lineattrs=(thickness=2 color=cxaf0000) name='se legendlabel='severe'; series x=vsdy y=vsstresn / group=vstpt lineattrs=(pattern=solid thickness=3) nomissinggroup name='bp' markerattrs=(symbol=circlefilled size=11); scatter x=vsdy y=vsstresn / group=vstpt markerattrs=(symbol=circlefilled size=11); scatter x=vsdy y=vsstresn / group=vstpt markerattrs=(symbol=circlefilled size=5 color=white); highlow y=yhigh low=xlow high=xhigh / highlabel=id labelattrs=(size=12); keylegend 'bp' / title='vitals:' across=3 valueattrs=(size=5) titleattrs=(size=8); keylegend 'mi' 'mo' 'se' / title='adverse Events:' across=3 valueattrs=(size=7) titleattrs=(size=8); rowaxis grid display=(nolabel) offsetmax=0.1; colaxis grid label='study Days' offsetmax=0.02 values=(&minday2 to &maxday by 2); run; 39
Lab Values Graph Data Here are the relevant columns from the LB data set that we will use to create the graph. We will use lbtestcd as the class variable. We will also use the AE reference lines. X, High and Low columns are used to draw the normal limit bands. 40
Lab Values Panel 41
Lab Values Panel This shows plots for three lab values over time. The normal limits for each statistic is shown as a band. AE event reference lines are shown. The VS name is shown in the row header on the right, and also as an inset for ease of readability. The zone where the lab value crosses beyond the normal limits is highlighted in red. 42
Code for Lab Values Panel title "Labs for Patient Id = &pid"; proc sgpanel data=lb2(where=(lbtestcd in ('AST' 'CREAT' 'URATE'))) noautolegend; panelby lbtestcd / columns=1 uniscale=column spacing=5 rows=3 layout=rowlattice novarname /*rowheaderpos=left*/; band x=lbdy lower=lbstnrmid upper=lbstresn / transparency=0.5 fillattrs=(color=red) fill outline; band x=lbdy lower=lbstresn upper=lbstnrmid / transparency=0.5 fillattrs=(color=red) fill outline; band x=lbdy lower=lbstnrlo upper=lbstnrhi / transparency=0 band fillattrs=(color=white) fill; x=lbdy lower=lbstnrlo upper=lbstnrhi / transparency=0.6 fillattrs=(color=lightblue) fill; refline -12 to 102 by 6 / axis=x lineattrs=graphgridlines; refline 0 / axis=x lineattrs=(thickness=1 color=black); refline mild / axis=x lineattrs=(color=cx00af00) name='mi' legendlabel='mild'; refline moderate / axis=x lineattrs=(color=cxcfaf00) name='mo' legendlabel='moder'; refline severe / axis=x lineattrs=(color=cxaf0000) series x=lbdy y=lbstresn / markers markerattrs=graphdata1(symbol=circlefilled size=19px) lineattrs=graphdata1(pattern=solid thickness=5); scatter x=lbdy y=lbstresn / name='se' legendlabel='severe'; markerattrs=( symbol=circlefilled size=11px color=white); highlow y=yhigh low=xlow high=xhigh / highlabel=lbtestcd labelattrs=(size=12); keylegend 'mi' 'mo' 'se' / title='adverse Events:' across=3; rowaxis display=(nolabel); colaxis label='study Days' offsetmax=0.02 values=(&minday2 to &maxday by 2); run; 43
Lab Values Panel Features Note the following features of the program: We draw a red band plot for each curve from value to mid level of the band. We the over lay a white band of the normal limits. Then we draw the normal limits and value line over this. We used a HighLow plot s HighLabel to draw the lab test name inside the cell. 44
Frequency of Medications Graph 45
Frequency of Medications Graph /*--Compute frequencies--*/ proc freq data=cm(keep=cmtrt) noprint; tables cmtrt / out=cmtrtf; run; /*--Merge frequency data with dates--*/ data cm3; format startdate enddate date9.; set meds(keep=cmtrt startdate enddate) cmtrtf; by cmtrt; startlabel='start Date'; endlabel='end Date'; run; /*--Medications frequency chart--*/ ods graphics / reset width=6.5in height=3in imagename="medfreq" ; title "Frequency of Medications for Patient Id = &pid"; proc sgplot data=cm3 noautolegend; hbarparm category=cmtrt response=count / dataskin=gloss datalabel; scatter y=cmtrt x=startlabel / markerchar=startdate x2axis; scatter y=cmtrt x=endlabel / markerchar=startdate x2axis; xaxis display=(nolabel) offsetmin=0.3; x2axis display=(nolabel noticks) offsetmax=0.78; yaxis display=(nolabel); run; 46
Frequency of Medications Graph Features Note the following features of the program: The X axis of the graph is restricted to the higher 70% of the axis space leaving 30% of the space vacant on the left. The two columns for start date and end date are drawn by using the MarkerChar option of the Scatter plot statement associated with the X2 axis. The X2 axis is restricted to the lower 22% of the axis space. 47
New Features with SAS 9.4 A new Axis Table statement is coming with SAS 9.4. This statement will make it even easier to display axis aligned statistics with other plots. Please come on by the SAS demo area for more information on these new features. 48
Resources I have a zip file of all the programs and extracted data. I will add it to the Focus Areas -> Graphics page soon. If you want, I can email the zip file to nyone that wants it now. http://blogs.sas.com/content/graphicallyspeaking/ 49