Hi Folks:
I have a few issues in the swimmer's plot shown below.
Question 1: Can you please help to achieve labels are ordered to:
Complete response
Partial response
Progressive disease
Prior Rx
Unrelated death
in the keylegend?
Currently, Prior Rx come up before Progressive disease which is not a logical order.
Question 2: How to show all Subject IDs in black? Right now, it takes different colors as the bar colors: green, purple and blue.
DATA SWIMMER2;
infile datalines dsd;
informat TRTCAP $12.;
informat BOR $20.;
INPUT SUBJID $ TRTSTDY TRTENDY ORDER TRTCAP $ BOR $ BORCD DDCRDY DEATH;
DATALINES;
14,1,28,1,,Progressive disease,1,,
19,1,28,2,FilledArrow,Partial response,2,30,
20,1,28,3,FilledArrow,Partial response,2,,
11,1,29,4,,Progressive disease,3,,
29,1,70,5,,Progressive disease,3,,72
12,1,91,6,,Complete response,1,,
15,1,91,7,FilledArrow,Partial response,2,,
17,1,91,8,FilledArrow,Complete response,1,93,
10,1,117,9,,Complete response,1,,
;
PROC SGPLOT DATA=SWIMMER2; title '';
STYLEATTRS DATACOLORS=(ORANGE BLUE GREEN);
HIGHLOW Y=ORDER LOW=TRTSTDY HIGH=TRTENDY / LOWLABEL=SUBJID TYPE=BAR
HIGHCAP=TRTCAP barwidth=0.75
LINEATTRS=(PATTERN=1) GROUP=BOR NAME='BOR' DATASKIN=CRISP;
SCATTER Y=ORDER X=DDCRDY/MARKERATTRS=(SYMBOL=STARFILLED SIZE=9)
NAME='DDCR' LEGENDLABEL='Prior Rx';
SCATTER Y=ORDER X=DEATH/MARKERATTRS=(SYMBOL=SQUAREFILLED COLORFILLED=RED SIZE=9)
NAME='DEATH' LEGENDLABEL='Unrelated death';
XAXIS LABEL='Study Day' VALUES=(0 TO 120 BY 30);
YAXIS LABEL='Subject ID' DISPLAY=(NOTICKS NOVALUES);
KEYLEGEND 'BOR' 'DDCR' 'DEATH' /
TITLE='' NOBORDER LOCATION=INSIDE POSITION=BOTTOMRIGHT ACROSS=1
SORTORDER=ASCENDING;
RUN;
DATA SWIMMER2; infile datalines dsd; informat TRTCAP $12.; informat BOR $20.; INPUT SUBJID $ TRTSTDY TRTENDY ORDER TRTCAP $ BOR $ BORCD DDCRDY DEATH; DATALINES; 14,1,28,1,,Progressive disease,1,, 19,1,28,2,FilledArrow,Partial response,2,30, 20,1,28,3,FilledArrow,Partial response,2,, 11,1,29,4,,Progressive disease,3,, 29,1,70,5,,Progressive disease,3,,72 12,1,91,6,,Complete response,1,, 15,1,91,7,FilledArrow,Partial response,2,, 17,1,91,8,FilledArrow,Complete response,1,93, 10,1,117,9,,Complete response,1,, ; PROC SGPLOT DATA=SWIMMER2; title ''; STYLEATTRS DATACOLORS=(ORANGE BLUE GREEN); HIGHLOW Y=ORDER LOW=TRTSTDY HIGH=TRTENDY / LOWLABEL=SUBJID TYPE=BAR labelattrs=(color=black) /*<-------*/ HIGHCAP=TRTCAP barwidth=0.75 LINEATTRS=(PATTERN=1) GROUP=BOR NAME='BOR' DATASKIN=CRISP; SCATTER Y=ORDER X=DDCRDY/MARKERATTRS=(SYMBOL=STARFILLED SIZE=9) NAME='DDCR' LEGENDLABEL='Prior Rx'; SCATTER Y=ORDER X=DEATH/MARKERATTRS=(SYMBOL=SQUAREFILLED COLORFILLED=RED SIZE=9) NAME='DEATH' LEGENDLABEL='Unrelated death'; XAXIS LABEL='Study Day' VALUES=(0 TO 120 BY 30); YAXIS LABEL='Subject ID' DISPLAY=(NOTICKS NOVALUES); KEYLEGEND 'BOR' 'DDCR' 'DEATH' / TITLE='' NOBORDER LOCATION=INSIDE POSITION=BOTTOMRIGHT ACROSS=1 /* SORTORDER=ASCENDING */; RUN;
"Pri" comes before "Pro" alphabetically so "Prior" will appear before "Progressive" which is the result of your use of the Keylegend option SORTORDER=ASCENDING
If you sort the data by BOR those variables values will appear in order and then the order of legend items can get what you want if you remove the Sortorder on the Keylegend.
LABELATTRS=() options apply to Lowlabel and Highlabel when used.
And for the thing you didn't ask about that annoys me is the single quote that appears as a title. Either provide a title or use the Title; to clear the current title definition.
proc sort data=swimmer2; by bor; run; title;
PROC SGPLOT DATA=SWIMMER2; STYLEATTRS DATACOLORS=(ORANGE BLUE GREEN); HIGHLOW Y=ORDER LOW=TRTSTDY HIGH=TRTENDY / LOWLABEL=SUBJID TYPE=BAR HIGHCAP=TRTCAP barwidth=0.75 labelattrs=(color=black) LINEATTRS=(PATTERN=1) GROUP=BOR NAME='BOR' DATASKIN=CRISP; SCATTER Y=ORDER X=DDCRDY/MARKERATTRS=(SYMBOL=STARFILLED SIZE=9) NAME='DDCR' LEGENDLABEL='Prior Rx'; SCATTER Y=ORDER X=DEATH/MARKERATTRS=(SYMBOL=SQUAREFILLED COLOR=RED SIZE=9) NAME='DEATH' LEGENDLABEL='Unrelated death'; XAXIS LABEL='Study Day' VALUES=(0 TO 120 BY 30); YAXIS LABEL='Subject ID' DISPLAY=(NOTICKS NOVALUES); KEYLEGEND 'BOR' 'DDCR' 'DEATH' / TITLE='' NOBORDER LOCATION=INSIDE POSITION=BOTTOMRIGHT ACROSS=1 ; RUN;
DATA SWIMMER2; infile datalines dsd; informat TRTCAP $12.; informat BOR $20.; INPUT SUBJID $ TRTSTDY TRTENDY ORDER TRTCAP $ BOR $ BORCD DDCRDY DEATH; DATALINES; 14,1,28,1,,Progressive disease,1,, 19,1,28,2,FilledArrow,Partial response,2,30, 20,1,28,3,FilledArrow,Partial response,2,, 11,1,29,4,,Progressive disease,3,, 29,1,70,5,,Progressive disease,3,,72 12,1,91,6,,Complete response,1,, 15,1,91,7,FilledArrow,Partial response,2,, 17,1,91,8,FilledArrow,Complete response,1,93, 10,1,117,9,,Complete response,1,, ; PROC SGPLOT DATA=SWIMMER2; title ''; STYLEATTRS DATACOLORS=(ORANGE BLUE GREEN); HIGHLOW Y=ORDER LOW=TRTSTDY HIGH=TRTENDY / LOWLABEL=SUBJID TYPE=BAR labelattrs=(color=black) /*<-------*/ HIGHCAP=TRTCAP barwidth=0.75 LINEATTRS=(PATTERN=1) GROUP=BOR NAME='BOR' DATASKIN=CRISP; SCATTER Y=ORDER X=DDCRDY/MARKERATTRS=(SYMBOL=STARFILLED SIZE=9) NAME='DDCR' LEGENDLABEL='Prior Rx'; SCATTER Y=ORDER X=DEATH/MARKERATTRS=(SYMBOL=SQUAREFILLED COLORFILLED=RED SIZE=9) NAME='DEATH' LEGENDLABEL='Unrelated death'; XAXIS LABEL='Study Day' VALUES=(0 TO 120 BY 30); YAXIS LABEL='Subject ID' DISPLAY=(NOTICKS NOVALUES); KEYLEGEND 'BOR' 'DDCR' 'DEATH' / TITLE='' NOBORDER LOCATION=INSIDE POSITION=BOTTOMRIGHT ACROSS=1 /* SORTORDER=ASCENDING */; RUN;
@Ksharp to order labels within variable: BOR in CR, PR and PD, I followed the blog: https://blogs.sas.com/content/graphicallyspeaking/2014/08/03/legend-order-in-sgplot-procedure/
step by step. Any idea why my labels are not ordered to CR, PR and PD even following this example?
data newcars; set SWIMMER2;
if BOR='CR' then mytype=1;
else if BOR='PR' then mytype=2;
else if BOR='PD' then mytype=3;
run;
proc sort data=newcars out=sortcars; by mytype; run;
data myfmt; set sortcars;
by mytype;
if first.mytype then do;
fmtname='typefmt';
start=mytype;
label=BOR;
drop BOR;
output; end; run;
proc format cntlin=myfmt;run;
ods graphics / width=450px height=350px;
PROC SGPLOT DATA=newcars; title '';
STYLEATTRS DATACOLORS=(ORANGE BLUE GREEN);
HIGHLOW Y=ORDER LOW=TRTSTDY HIGH=TRTENDY / LOWLABEL=SUBJID TYPE=BAR
LABELATTRS=(COLOR=BLACK SIZE=10)
HIGHCAP=TRTCAP barwidth=0.75 LINEATTRS=(PATTERN=1) GROUP=BOR NAME='BOR' DATASKIN=SHEEN;
SCATTER Y=ORDER X=DDCRDY/MARKERATTRS=(SYMBOL=STARFILLED SIZE=9)
NAME='DDCR' LEGENDLABEL='Prior CD19 CAR T-cell therapy';
SCATTER Y=ORDER X=DEATH/MARKERATTRS=(SYMBOL=SQUAREFILLED COLOR=RED SIZE=9)
NAME='DEATH' LEGENDLABEL='Unrelated event';
XAXIS LABEL='Study Day' VALUES=(0 TO 120 BY 30);
YAXIS LABEL='Subject ID' DISPLAY=(NOTICKS NOVALUES);
KEYLEGEND 'BOR' 'DDCR' 'DEATH' 'DISC'/valueattrs=(size=10)
TITLE='' NOBORDER LOCATION=INSIDE POSITION=BOTTOMRIGHT ACROSS=1;
format mytype typefmt.;
RUN;
Follow ballardw the suggestion. Add one more PROC SORT before it.
DATA SWIMMER2; infile datalines dsd; informat TRTCAP $12.; informat BOR $20.; INPUT SUBJID $ TRTSTDY TRTENDY ORDER TRTCAP $ BOR $ BORCD DDCRDY DEATH; DATALINES; 14,1,28,1,,Progressive disease,1,, 19,1,28,2,FilledArrow,Partial response,2,30, 20,1,28,3,FilledArrow,Partial response,2,, 11,1,29,4,,Progressive disease,3,, 29,1,70,5,,Progressive disease,3,,72 12,1,91,6,,Complete response,1,, 15,1,91,7,FilledArrow,Partial response,2,, 17,1,91,8,FilledArrow,Complete response,1,93, 10,1,117,9,,Complete response,1,, ; proc sort data=swimmer2; by bor; run; PROC SGPLOT DATA=SWIMMER2; title ''; STYLEATTRS DATACOLORS=(ORANGE BLUE GREEN); HIGHLOW Y=ORDER LOW=TRTSTDY HIGH=TRTENDY / LOWLABEL=SUBJID TYPE=BAR labelattrs=(color=black) /*<-------*/ HIGHCAP=TRTCAP barwidth=0.75 LINEATTRS=(PATTERN=1) GROUP=BOR NAME='BOR' DATASKIN=CRISP; SCATTER Y=ORDER X=DDCRDY/MARKERATTRS=(SYMBOL=STARFILLED SIZE=9) NAME='DDCR' LEGENDLABEL='Prior Rx'; SCATTER Y=ORDER X=DEATH/MARKERATTRS=(SYMBOL=SQUAREFILLED COLORFILLED=RED SIZE=9) NAME='DEATH' LEGENDLABEL='Unrelated death'; XAXIS LABEL='Study Day' VALUES=(0 TO 120 BY 30); YAXIS LABEL='Subject ID' DISPLAY=(NOTICKS NOVALUES); KEYLEGEND 'BOR' 'DDCR' 'DEATH' / TITLE='' NOBORDER LOCATION=INSIDE POSITION=BOTTOMRIGHT ACROSS=1 /* SORTORDER=ASCENDING */; RUN;
Oh. That is easy. Just padding some blanks before BOR. the first order BOR padding the most blanks. data swimmer2; set swimmer2; if BOR='Complete response' then BOR=' Complete response'; if BOR='Partial response' then BOR=' Partial responsee'; if BOR='Progressive disease' then BOR='Progressive disease'; run;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.