BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
wj2
Quartz | Level 8 wj2
Quartz | Level 8

Hello, 

 

I am trying to combine 4 separate survival plots into a single, panel style graph. Please see below for my code for each of the individual survival plots. Any help with this would be greatly appreciated! 

/***Graph #1***/
ods graphics on;
ods output survivalplot=OverallSample;
proc lifetest data=have plots=survival; 
time Days*censor(0);
run;
ods graphics off;

proc sgplot data=OverallSample;  
step y=survival x=time;
run;

/***Graph #2***/
ods graphics on;
ods output survivalplot=VariableA;
proc lifetest data=have plots=survival; 
strata varA;
time Days*censor(0);
run;
ods graphics off;

proc sgplot data=VariableA;  
step y=survival x=time/ group=stratum;
run;

/***Graph #3***/
ods graphics on;
ods output survivalplot=VariableB;
proc lifetest data=have plots=survival; 
strata varB;
time Days*censor(0);
run;
ods graphics off;

proc sgplot data=VariableB;  
step y=survival x=time/ group=stratum;
run;

/***Graph #4***/
ods graphics on;
ods output survivalplot=VariableC;
proc lifetest data=have plots=survival; 
strata varC;
time Days*censor(0);
run;
ods graphics off;

proc sgplot data=VariableC;  
step y=survival x=time/ group=stratum;
run;
1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

Here is one way that uses SGPANEL and combining data to add a variable to indicate which panel the values go in and setting a common Group=variable so the same code can be used for the plot statement. You should have the SASHELP.CLASS data set available so you can see if this is similar in functionality to what you want.

data example;
   set sashelp.class (in=in1)
       sashelp.class (in=in2)
       sashelp.class (in=in3)
   ;
   length Groupvar $ 3;
   if in1 then do;
      Plot=1;
      Groupvar='All';
   end;
   else if in2 then do;
      Plot=2;
      Groupvar=sex;
   end;
   else if in3 then do;
      Plot=3;
      Groupvar= put(age,2.);
   end;
run;

proc sgpanel data=example;
   panelby Plot;
   scatter x=height y=weight/group=groupvar;
run;

The IN= data set option creates a temporary true/false (1/0) variable that indicates whether the current record the data step is processing has values from the given data set.

 

With multiple data sets built the way you show you would only need to make sure that the "overall" data set has a group variable value to use this approach after adding the plot indicator.

View solution in original post

10 REPLIES 10
JeffMeyers
Barite | Level 11

Hello,

  You might be interested in a macro I've written that can do this: %NEWSURV .  It's a macro that creates high quality KM curves along with calculating a lot of statistics.  You can plot multiple graphs in the same image (see example 7 in the link). 

 

Otherwise a strategy I think you could potentially use would be to make a variable that you can use in a BY statement and then use SGPANEL instead of SGPLOT:

 

data have2;
   set have;
   length graph 8. strat $200.;
   graph=1;strat='';output;
   graph=2;strat=vvalue(varA);output;
   graph=3;strat=vvalue(varB);output;
   graph=4;strat=vvalue(varC);output;
run;
ods output survivalplot=Graph;
proc lifetest data=have2 plots=survival;
by graph;
strata strat;
time days*censor(0);
run;
proc sgpanel data=graph;
  panelby graph / rows=2 columns=2;
  step y=survival x=time/ group=stratum;
run;

The code isn't tested or perfect, but would at least be a step in the right direction.

 

ballardw
Super User

Here is one way that uses SGPANEL and combining data to add a variable to indicate which panel the values go in and setting a common Group=variable so the same code can be used for the plot statement. You should have the SASHELP.CLASS data set available so you can see if this is similar in functionality to what you want.

data example;
   set sashelp.class (in=in1)
       sashelp.class (in=in2)
       sashelp.class (in=in3)
   ;
   length Groupvar $ 3;
   if in1 then do;
      Plot=1;
      Groupvar='All';
   end;
   else if in2 then do;
      Plot=2;
      Groupvar=sex;
   end;
   else if in3 then do;
      Plot=3;
      Groupvar= put(age,2.);
   end;
run;

proc sgpanel data=example;
   panelby Plot;
   scatter x=height y=weight/group=groupvar;
run;

The IN= data set option creates a temporary true/false (1/0) variable that indicates whether the current record the data step is processing has values from the given data set.

 

With multiple data sets built the way you show you would only need to make sure that the "overall" data set has a group variable value to use this approach after adding the plot indicator.

wj2
Quartz | Level 8 wj2
Quartz | Level 8

@ballardw Thank you very much for the help! This code appears to generally work; however, for some reason, I am getting an extra line for each of my four graphs that sort of borders the bottom-left of the graph- please see example below. Do you have any suggestions on how to address this issue? I have provided my code below for your reference. Also, would you be able to provide any suggestions on how to modify the appearance of each individual graph of the panel, such as adding different color lines for the groups, modifying the legend labels for each graph, and adding the logrank values for each graph? 

 

Example graph with extra line:

SurvCurve.PNG

 

 

 

 

 

 

 

 

 

 

 

Code: 

data panel;
   set have (in=in1)
         have (in=in2)
         have (in=in3)
	 have (in=in4)
   ;
   length Groupvar $ 3;
   if in1 then do;
      Plot=1;
      Groupvar='Any';
   end;
   else if in2 then do;
      Plot=2;
      Groupvar=varA;
   end;
   else if in3 then do;
      Plot=3;
      Groupvar=varB;
   end;
   else if in4 then do;
      Plot=4;
      Groupvar=varC;
   end;
run;

ods graphics on;
ods output survivalplot=panel_graph;
proc lifetest data=panel plots=survival;
by plot;
strata groupvar;
time days*censor(0);
run;
ods graphics off;

proc sgpanel data=panel_graph;
   panelby Plot;
   step y=survival x=time/group=plot lineattrs=(thickness=1) ;
  colaxis label="Time to discontinuation (Days)" values=(0 to 180 by 30) labelattrs=(weight=bold);
rowaxis label="Survival probability" values=(0 to 1 by 0.2) labelattrs=(weight=bold) grid;
run;
JeffMeyers
Barite | Level 11
Your group variable should be groupvar and not plot in the step statement.
wj2
Quartz | Level 8 wj2
Quartz | Level 8

@JeffMeyers  Thank you!! Totally overlooked that! 

 

Also, would you be able to suggest how the line attributes could be modified for each individual graph using sgpanel? This seems pretty straightforward using 'STYLEATTRS' for a single graph, but I'm wondering how individual graphs could be modified when Proc Sgpanel is being used. For instance, I would like to have different colors for each of the groupvar levels for each plot. FYI, I have one level for groupvar for Plot=1, 2 levels for groupvar for Plot=2 and Plot=3, and 4 levels for groupvar for Plot=4. 

JeffMeyers
Barite | Level 11
I think there would be a way to do this with a discrete attribute map. You can look up how to make one here:
https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/grstatproc/n18szqcwir8q2nn10od9hhdh2ksj.htm
wj2
Quartz | Level 8 wj2
Quartz | Level 8

@JeffMeyers thank you, this is exactly what I needed! 

 

Also, would you or someone else happen to know how to create separate legends for each panel to include INSIDE each panel? 

JeffMeyers
Barite | Level 11
Unfortunately that would require getting into GTL coding I believe. I'm sorry I should have thought of this originally. If you want something automated for this the macro I linked to in my original reply is really powerful for this.
Otherwise here's a link to another post with that question: https://communities.sas.com/t5/Graphics-Programming/Can-we-create-a-separate-legend-for-each-panel-i...
DanH_sas
SAS Super FREQ

Another possibility that has not been mentioned is to use ODS LAYOUT to layout each of your SGPLOT outputs into a grid on a page. Would you be interested in that approach?

ballardw
Super User

The vertical and horizontal lines are caused by some record with a Y variable value of 0 and X variable value of 0.

 

It may be that you want to exclude those from your plot data set.

 

Since there is no legend in your picture I can't say which group variable is associated with which line. I suspect that one of the (0,0) pairs is the first record of a group variable value (the black vertical line) and the the other, the blue line, is likely the last record of the group. So look at the first and last records of Have and see if you actually want those points on the plot.

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 10 replies
  • 6692 views
  • 6 likes
  • 4 in conversation