I am looking to produce a forest plot with YAXISTABLES using SAS 9.04.01M3
The labels for the table are not splitting in the correct place and I'd like to dictate where the splits occur (i'd like Placebo/Active on first line, N=XX on second and n/M (%) on third)
Plot examples below
I have tried various escape character options:
SAS Code:
data WORK.PLOTDATA3; infile datalines dsd truncover; input sgval:32. indentl:32. plab:$40. n_pbo:$15. n_act:$15. valtab:$18. OddsRatioEst:ODDSR8.3 LowerCL:ODDSR8.3 UpperCL:ODDSR8.3 yval:32. orref:32. xl:32. text:$1.; format OddsRatioEst ODDSR8.3 LowerCL ODDSR8.3 UpperCL ODDSR8.3; label OddsRatioEst="Odds Ratio" LowerCL="Wald Lower Confidence Limit for Odds Ratio" UpperCL="Wald Upper Confidence Limit for Odds Ratio"; datalines; 1 0 Overall . . . 1 . . 2 1 Overall xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.713 1.288 2.279 2 1.7130795416 . 1 0 Baseline Clinical Status . . . 3 . . 2 1 Hosp. HF Oxy, NIV xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.714 1.073 2.738 4 . . 2 1 Hosp. Int, MV xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.712 1.195 2.454 5 . . 1 0 Age Group . . . 6 . . 2 1 <60 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.580 1.055 2.366 7 . . 2 1 60 to <70 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 2.197 1.361 3.545 8 . . 2 1 70 to <80 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.211 0.569 2.577 9 . . 1 0 Baseline Clinical Status, Age Group . . . 10 . . 2 1 Hosp. HF Oxy, NIV, <60 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.634 1.166 2.290 11 . . 2 1 Hosp. HF Oxy, NIV, 60 to <70 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.634 1.166 2.290 12 . . 2 1 Hosp. HF Oxy, NIV, 70 to <80 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.634 1.166 2.290 13 . . 2 1 Hosp. Int, MV , <60 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 1.634 1.166 2.290 14 . . 2 1 Hosp. Int, MV , 60 to <70 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 2.433 1.412 4.191 15 . . 2 1 Hosp. Int, MV , 70 to <80 years xxx/xxx (xxx%) xxx/xxx (xxx%) x.xx (x.xx,x.xx) 0.984 0.431 2.248 16 . . . . . . . 17 . 2 O . . . . . 17 . 0.5 P ;;;; PROC SGPLOT DATA=plotdata3 DATTRMAP=attrmap NOBORDER NOWALL NOAUTOLEGEND; FORMAT text $txt.; STYLEATTRS axisextent=data; REFLINE 1 / AXIS=x LINEATTRS=(THICKNESS=2 COLOR=grey); REFLINE orref / AXIS=x LINEATTRS=(THICKNESS=1 COLOR=grey PATTERN=2); SCATTER X=oddsratioest Y=yval / XERRORLOWER=lowercl XERRORUPPER=uppercl MARKERATTRS=(SYMBOL=CIRCLEFILLED SIZE=9 COLOR="BLACK") ERRORBARATTRS=(COLOR="BLACK") ; YAXISTABLE plab / POSITION=left LOCATION=inside INDENTWEIGHT=indentl TEXTGROUP=sgval TEXTGROUPID=text VALUEATTRS=(size=9) NOLABEL; YAXISTABLE n_pbo n_act valtab / POSITION=right LOCATION=inside VALUEATTRS=(size=9) VALUEHALIGN=center LABELATTRS=(SIZE=9); TEXT x=xl y=yval text=text / POSITION=bottom CONTRIBUTEOFFSETS=none STRIP TEXTATTRS=(SIZE=9); YAXIS DISPLAY=none REVERSE FITPOLICY=NONE OFFSETMAX=0.04 OFFSETMIN=0; XAXIS LABEL="Odds Ratio" LABELPOS=DATACENTER VALUEATTRS=(SIZE=10) MIN=0 MAX=8 TYPE=log VALUES=(0.25, 0.5, 1.0, 2.0, 4.0, 8.0); LABEL valtab = "OR (95% CI)" n_pbo = "Placebo N=XX n/M (%)" n_act = "Active N=XX n/M (%)"; RUN;
Please copy your data step from your post, paste into your SAS editor and run the data step.
Then check if you really meant to use ODDSR8.3 as an informat. Since ODDSR is not a SAS supplied informat we can't use that and in many cases you really do not want to include a decimal bit with the informat unless you want SAS to imply a non-existant decimal position.
Reading a value like 123456 with an informat of 6.2 yields a value o f1234.56
When you can provide a data step that will run completely then we'll be in a better position to answer questions.
I used the supplied code to generate the datastep, shame it doesn't work...: https://communities.sas.com/t5/SAS-Communities-Library/How-to-create-a-data-step-version-of-your-dat... As I didn't create the informat it must be a SAS supplied informat (perhaps in SAS Stat)?
Anyway new code below:
data WORK.PLOTDATA3;
infile datalines dsd truncover delimiter='#';
input sgval:32. indentl:32. plab:$40. n_pbo:$15. n_act:$15. valtab:$18. OddsRatioEst:8.3 LowerCL:8.3 UpperCL:8.3 yval:32. orref:32. xl:32. text:$1.;
label OddsRatioEst="Odds Ratio" LowerCL="Wald Lower Confidence Limit for Odds Ratio" UpperCL="Wald Upper Confidence Limit for Odds Ratio";
datalines;
1#0#Overall####.#.#.#1#.#.
2#1#Overall#xxx/xxx (xxx%)#xxx/xxx (xxx%)#x.xx (x.xx,x.xx)#1.713#1.288#2.279#2#1.7130795416#.
1#0#Baseline Clinical Status#####.#.#3#.#.#
2#1#Hosp. HF Oxy, NIV#xxx/xxx (xxx%)#xxx/xxx (xxx%)#x.xx (x.xx,x.xx)#1.714#1.073#2.738#4#.#.
2#1#Hosp. Int, MV#xxx/xxx (xxx%)#xxx/xxx (xxx%)#x.xx (x.xx,x.xx)#1.712#1.195#2.454#5#.#.
1#0#Age Group####.#.#.#6#.#.
2#1#<60 years#xxx/xxx (xxx%)#xxx/xxx (xxx%)#x.xx (x.xx,x.xx)#1.580#1.055#2.366#7#.#.
2#1#60 to <70 years#xxx/xxx (xxx%)#xxx/xxx (xxx%)#x.xx (x.xx,x.xx)#2.197#1.361#3.545#8#.#.
2#1#70 to <80 years#xxx/xxx (xxx%)#xxx/xxx (xxx%)#x.xx (x.xx,x.xx)#1.211#0.569#2.577#9#.#.
.#.#####.#.#.#10#.#2#O
.#.#####.#.#.#10#.#0.5#P
;;;;
https://www.pharmasug.org/proceedings/2017/DV/PharmaSUG-2017-DV03.pdf
You might be interested in my paper with Mary Beth Herring. Search for "split".
Thanks, that appears to work for Rowlabels, and I suppose you could convert the "labels" into rows in your yaxistable when you want a column label, but that seems a bit clumsy I was hoping there was a simple way...
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.