BookmarkSubscribeRSS Feed
jsbyxws
Obsidian | Level 7

I have a dummy dataset with 3 cohorts: 1, 2 and 3. In each cohort there are subjects (Cohort 1: 011, 012. Cohort2: 021. Cohort 3: 031). I want the keylegend to show 3 rows with row 1 "Cohort 1: 011 012", row 2 "Cohort 2: 021", and row 3 "Cohort 3: 031". I don't know how. Below is the data and plot.

data test;
	cohort = 1;subjid = '011';aval = 10; ady = 1; output;
	cohort = 1;subjid = '012';aval = 15; ady = 1; output;
	cohort = 2;subjid = '021';aval = 20; ady = 2; output;
	cohort = 3;subjid = '031';aval = 30; ady = 3; output;
run;

proc sort data=test; by cohort subjid; run;

proc sgpanel data=test;
	panelby cohort / columns=1 spacing=5 novarname HEADERATTRS=(Family=Arial Size=11 Weight=Bold);
	series x=ady y=aval / markers group=subjid markerattrs=(symbol=circle) ;
	keylegend /title='Subject' titleattrs=(size=8 family='Arial' weight=bold);

	colaxis offsetmin=0.05 offsetmax=0.01 values=(-1 1 2 3 ) valueattrs=(weight=bold size=8 family='Arial')
	      valuesdisplay=('Baseline' 'Day 1' 'Day 2' 'Day 3') 
	      label='Study Day' labelattrs=(weight=bold size=11 family='Arial') fitpolicy=rotate;
	rowaxis label="Param" labelattrs=(weight=bold family='Arial' size=11);

	refline 1 / axis=x lineattrs=(thickness=1 color=lightgray pattern=solid);
run;
6 REPLIES 6
ballardw
Super User

I think this comes close to what you are asking for.

Separate legends sort of imply separate plots. So the data is changed to plot a different y variable in each plot panel. Then use the EXCLUDE= option for each separate keylegend to only show the subjid for the cohort.

data test;
	cohort = 1;subjid = '011';aval = 10; ady = 1; output;
	cohort = 1;subjid = '012';aval = 15; ady = 1; output;
	cohort = 2;subjid = '021';aval2 = 20; ady = 2; output;
	cohort = 3;subjid = '031';aval3 = 30; ady = 3; output;
run;

proc sort data=test; by cohort subjid; run;

proc sgpanel data=test;
	panelby cohort / columns=1 spacing=5 novarname HEADERATTRS=(Family=Arial Size=11 Weight=Bold);
	series x=ady y=aval / markers group=subjid markerattrs=(symbol=circle) name='p1' ;
	series x=ady y=aval2 / markers group=subjid markerattrs=(symbol=circle) name='p2' ;
	series x=ady y=aval3 / markers group=subjid markerattrs=(symbol=circle) name='p3' ;
	keylegend 'p1' /title='Corhort 1' exclude=('021' '031') titleattrs=(size=8 family='Arial' weight=bold);
	keylegend 'p2' /title='Corhort 2' exclude=('011' '012' '031') titleattrs=(size=8 family='Arial' weight=bold);
	keylegend 'p3' /title='Corhort 3' exclude=('011' '012' '021') titleattrs=(size=8 family='Arial' weight=bold);

	colaxis offsetmin=0.05 offsetmax=0.01 values=(-1 1 2 3 ) valueattrs=(weight=bold size=8 family='Arial')
	      valuesdisplay=('Baseline' 'Day 1' 'Day 2' 'Day 3') 
	      label='Study Day' labelattrs=(weight=bold size=11 family='Arial') fitpolicy=rotate;
	rowaxis label="Param" labelattrs=(weight=bold family='Arial' size=11);

	refline 1 / axis=x lineattrs=(thickness=1 color=lightgray pattern=solid);
run;

There might be a cleaner way with Annotate data.

jsbyxws
Obsidian | Level 7

Hi Ballardw,

 

Thanks a lot for help! It works!

 

The actual data has about many cohorts. Each cohort has 3 subjects. It would be tedious to exclude so many subjects in reality.

 

 

Ksharp
Super User
data test;
	cohort = 1;subjid = '011';aval = 10; ady = 1; output;
	cohort = 1;subjid = '012';aval = 15; ady = 1; output;
	cohort = 2;subjid = '021';aval = 20; ady = 2; output;
	cohort = 3;subjid = '031';aval = 30; ady = 3; output;
run;

proc sort data=test; by cohort subjid; run;

proc sgpanel data=test;
	panelby cohort / columns=1 spacing=5 novarname HEADERATTRS=(Family=Arial Size=11 Weight=Bold);
	series x=ady y=aval / markers group=subjid markerattrs=(symbol=circle) ;

legenditem name='a' type=MARKERLINE / label='011' MARKERATTRS=graphdata1 LINEATTRS=graphdata1;
legenditem name='b' type=MARKERLINE / label='012' MARKERATTRS=graphdata2 LINEATTRS=graphdata2;
legenditem name='c' type=MARKERLINE / label='021' MARKERATTRS=graphdata3 LINEATTRS=graphdata3;
legenditem name='d' type=MARKERLINE / label='031' MARKERATTRS=graphdata4 LINEATTRS=graphdata4;



keylegend 'a' 'b' /title='Corhort 1' titleattrs=(size=8 family='Arial' weight=bold) noborder;
keylegend 'c' /title='Corhort 2' titleattrs=(size=8 family='Arial' weight=bold) noborder;
keylegend 'd' /title='Corhort 3' titleattrs=(size=8 family='Arial' weight=bold) noborder;

	colaxis offsetmin=0.05 offsetmax=0.01 values=(-1 1 2 3 ) valueattrs=(weight=bold size=8 family='Arial')
	      valuesdisplay=('Baseline' 'Day 1' 'Day 2' 'Day 3') 
	      label='Study Day' labelattrs=(weight=bold size=11 family='Arial') fitpolicy=rotate;
	rowaxis label="Param" labelattrs=(weight=bold family='Arial' size=11);

	refline 1 / axis=x lineattrs=(thickness=1 color=lightgray pattern=solid);
run;

Ksharp_0-1678453427153.png

 

jsbyxws
Obsidian | Level 7

Thanks a lot, KSharp! 

 

Yes, it solves this problem.

 

But in reality, the study has about 50 subjects with 15 cohort. How to make legend item list easier to code?

 

Another information: if each cohort is 3 subjects, crossover = 3 will make it multiple rows in 3 columns. But how to add cohort label "Cohort 1", "Cohort 2" etc?

ballardw
Super User

@jsbyxws wrote:

Thanks a lot, KSharp! 

 

Yes, it solves this problem.

 

But in reality, the study has about 50 subjects with 15 cohort. How to make legend item list easier to code?

 

Another information: if each cohort is 3 subjects, crossover = 3 will make it multiple rows in 3 columns. But how to add cohort label "Cohort 1", "Cohort 2" etc?


That would likely be ugly in SGPANEL.

Did you try SGPLOT:

Consider that with a BY statement then each legend is built separately and by default each plot will have the By information:

data test;
	cohort = 1;subjid = '011';aval = 10; ady = 1; output;
	cohort = 1;subjid = '012';aval = 15; ady = 1; output;
	cohort = 2;subjid = '021';aval = 20; ady = 2; output;
	cohort = 3;subjid = '031';aval = 30; ady = 3; output;
run;

proc sort data=test; by cohort subjid; run;

proc sgplot data=test;
   by cohort;
/*	panelby cohort / columns=1 spacing=5 novarname HEADERATTRS=(Family=Arial Size=11 Weight=Bold);*/
	series x=ady y=aval / markers group=subjid markerattrs=(symbol=circle) ;
	keylegend /title='Subject' titleattrs=(size=8 family='Arial' weight=bold);

	xaxis offsetmin=0.05 offsetmax=0.01 values=(-1 1 2 3 ) valueattrs=(weight=bold size=8 family='Arial')
	      valuesdisplay=('Baseline' 'Day 1' 'Day 2' 'Day 3') 
	      label='Study Day' labelattrs=(weight=bold size=11 family='Arial') fitpolicy=rotate;
	yaxis label="Param" labelattrs=(weight=bold family='Arial' size=11);

	refline 1 / axis=x lineattrs=(thickness=1 color=lightgray pattern=solid);
run;

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 552 views
  • 2 likes
  • 3 in conversation