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

 

The MVMODELS macro has some nice formatting capabilities for producing forest plots from a multivariable logistic regression. However I am unable to add interaction terms like I can with just running proc logistic.

https://communities.sas.com/t5/SAS-Communities-Library/MVMODELS-a-Macro-for-Survival-and-Logistic-An...

 

The macro code for MVMODELS exports parameterestimates from proc logistic, but I have limited expertise with macro coding. Is there a method to alter the MVMODEL code so that I can enter the interaction terms according to  sex*race or sex|race and have the MVMODEL plot the estimates as shown in the proc logistic forest plot but still be formatted as the MVMODEL forest plot?

If that makes sense.

 

I have an input dataset called infarct.

I ran proc logistic, modeling infarct as event='Yes' (for some reason SAS gave me an error when I modeled infarct for event=1 using the unformatted dataset), and it gives me a forest plot with the interaction terms between Sex and Race.

 

Data infarct ;
infile datalines delimiter="," ;
input BBlocker Alcohol Smoking Sex $ Race :$9. Age BMI TG Cpeptide Glucose Infarct @@;
datalines;
0,1,0,F,non-white,78,19.3,1.1,0.4,6.6,1
0,1,0,M,white,72,24.6,2.3,1.9,8.6,1
0,0,0,M,non-white,61,25.2,0.7,4.1,5.7,0
0,1,1,M,non-white,62,24.9,1,3.9,8.7,1
0,1,1,F,non-white,55,23.4,2.1,2.5,6.2,0
0,0,0,M,white,51,24.8,0.9,6.6,9.1,0
0,0,0,F,non-white,65,22.2,1.6,0.7,15.1,0
0,1,0,M,white,71,27.7,2.2,2.4,5.7,0
0,1,1,M,white,64,26.4,2.2,0.6,11.2,1
0,0,0,M,non-white,56,27.8,1.2,1.3,6.8,0
0,1,1,F,non-white,54,30.9,2.1,0.9,3.8,0
0,0,0,M,white,71,21.9,0.8,2.3,7.7,0
0,0,1,F,non-white,57,21.2,1.8,1.5,8.2,0
0,0,0,M,non-white,64,27.7,1.4,1.1,13.9,0
0,1,0,F,white,76,26.6,1.6,1.5,7.2,1
0,0,0,F,white,77,26.7,1.4,4.7,8.8,0
0,0,0,F,non-white,63,26.8,1.1,1.7,7.6,0
0,0,0,M,white,74,30.7,1.6,2.3,10.8,0
0,1,0,M,white,65,22.2,1.3,0.6,11.8,1
0,0,0,M,white,83,23.4,1.2,1.8,17.2,0
0,1,0,F,white,59,24.5,1.4,2.3,10.7,1
0,1,0,M,non-white,57,23.7,0.6,2.5,6.9,1
0,1,0,F,non-white,73,18.6,1.3,1.5,9.2,1
0,1,1,M,white,74,32.2,1.7,1.9,8.4,1
0,0,0,F,non-white,48,26.3,1.2,1.7,8.3,0
0,0,0,F,white,55,21.2,2.1,1.7,13.6,0
0,1,0,F,non-white,66,30.3,0.8,3.4,6,0
0,0,1,F,white,52,29.8,0.7,4.5,4,0
0,1,0,M,white,56,26.9,1.6,1,10.6,1
0,0,0,M,white,74,23.6,2,2.1,8.3,0
1,1,1,F,white,61,22.3,2.1,2.4,10.1,0
1,1,1,M,non-white,69,25.4,2.4,1.3,11.2,1
1,1,0,F,non-white,60,29.3,2.5,1.5,11.8,1
1,1,1,M,white,55,34.5,3.4,0.8,10.8,1
1,0,0,M,non-white,57,25.9,0.6,2.5,6.6,0
1,0,0,M,non-white,67,35,1.2,2.1,8.2,1
1,1,0,M,non-white,43,26.8,1.7,1.2,10.4,1
1,1,0,M,white,63,32.1,2.5,3.1,4.3,0
1,0,0,M,white,68,26.3,1.5,3.2,10.8,0
1,1,1,M,non-white,65,34.1,4.1,0.9,8.3,1
1,0,0,F,non-white,47,23.4,1.7,1.5,6.8,0
1,1,0,F,non-white,50,28.6,2.3,2.5,11.9,1
1,1,1,F,non-white,53,28.6,1.3,2.5,10.7,0
1,0,0,F,non-white,65,32.2,0.6,2.3,9.7,0
1,1,1,M,non-white,68,26.1,0.6,2.3,5.7,0
1,0,0,M,non-white,53,26.7,0.6,2.5,8.3,0
1,1,0,M,non-white,60,31.2,1.9,1.9,7.2,1
1,0,0,M,non-white,59,33.2,1.1,2.9,16.7,0
1,1,1,F,non-white,57,28.1,3.9,2.7,8.7,1
1,0,0,M,white,59,23.9,2.5,1.9,13.6,0
1,1,1,M,non-white,69,25.7,0.9,0.8,10.6,1
1,1,0,M,white,59,23.5,7.4,1.9,13.9,0
1,0,1,F,non-white,67,29.6,2.1,5.1,11.9,1
1,1,0,F,non-white,66,32.6,2.3,6.1,6,0
1,1,0,F,white,58,27.8,0.9,1.7,9.1,0
1,0,1,M,non-white,54,33.9,1.8,1.7,8.4,1
1,0,0,F,white,64,24.4,1.9,2.4,9.1,0
1,1,0,F,white,52,27.5,2.3,2.3,10.9,1
1,1,0,F,white,48,27.4,2.9,1.7,7.7,1
1,1,0,F,non-white,62,32.3,4.7,2.1,8.8,1
1,1,1,F,non-white,50,25.9,2.4,1.1,20.7,1
1,0,1,M,white,56,24,1.7,4.5,10.6,0
1,1,0,M,non-white,70,24.5,4.5,0.8,15.1,1
1,0,0,F,white,58,35.7,1.5,3.2,17,0
1,1,0,F,non-white,62,29.6,1.1,3.4,8.4,0
1,0,0,F,non-white,62,27.4,1,4.7,8.6,0
1,1,0,F,non-white,68,30.3,1.5,3.9,9.2,1
1,1,0,F,white,53,29.5,0.7,2.4,9.2,0
1,0,1,F,non-white,68,29.7,1.5,1.8,11.2,1
1,1,0,F,non-white,62,25.7,2.4,4.1,10.8,1
1,1,1,F,non-white,58,29.8,0.6,1.1,7.6,0
;
run;

proc format;
value Infarctfmt 0 = "No"
1 = "Yes"
;
value BBlockerfmt 0 = "No"
1 = "Yes"
;
value Alcoholfmt 0 = "No"
1 = "Yes"
;
value Smokingfmt 0 = "No"
1 = "Yes"
;
run;

data infarct;
set infarct;
format infarct Infarctfmt.;
format alcohol Alcoholfmt.;
format BBlocker BBlockerfmt.;
format smoking Smokingfmt.;
run;

proc logistic data=infarct  plots(only)=(EFFECT ODDSRATIO(logbase=10   TYPE=HORIZONTALSTAT ));
class BBlocker(ref='No') Alcohol(ref='Yes') Smoking(ref='Yes') Sex(ref='M') Race(ref='non-white') /param=ref ;
model infarct(event='Yes')=  BBlocker Alcohol Smoking Sex|Race Age BMI TG Cpeptide Glucose /  orpvalue clodds=wald  lackfit;
oddsratio BBlocker /  cl=wald;
oddsratio Alcohol /  cl=wald;
oddsratio Smoking /  cl=wald;
oddsratio Sex / cl=wald;
oddsratio Race / cl=wald;
oddsratio Age / cl=wald;
oddsratio BMI / cl=wald;
oddsratio  TG / cl=wald;
oddsratio Cpeptide / cl=wald;
oddsratio Glucose / cl=wald;
run;
quit;

Forest Plot from proc logisticForest Plot from proc logistic

 

Code for MVMODEL (I've attached a modified version that adds the option for third reference line) does not allow me to enter interaction terms, but I like the way it's formatted and how the odds ratios and confidence intervals are limited to 2 decimal places:

 

%mvmodels (DATA=infarct, METHOD=LOGISTIC, NMODELS=1,
    EVENTCOV=infarct,EVENT=Yes,COVARIATES=BBlocker Alcohol Smoking Sex Race Age BMI TG Cpeptide Glucose, TYPE=2 2 2 2 2 1 1 1 1 1 ,
    CONT_DISPLAY=2, CAT_DISPLAY=4, cat_param=ref, cat_ref=No`Yes`Yes`M`non-white, 
    XAXISTYPE=log, LOGBASE=10, XAXISLABEL=Odds Ratios (log scale),
    PVAL_TYPE3=0, 
DISPLAY=subtitle or_plot or_est_range , show_adjcovariates=1, pval_covariates=1, refline=1,  SREFLINE=0.5, SREFLINEPATTERN=SHORTDASH, 
 TREFLINE=1.5, TREFLINEPATTERN=SHORTDASH, LOGTICKSTYLE = LOGEXPAND, LOGMINOR=TRUE, 
 LINECOLOR=blue, labels=Beta Blocker``Smoking Status```Age in years`BMI (%)`Triglycerides (mmol/L)`C-Peptide (nmol/L)`HbA1c (%),REFGUIDELOWER=Lower Odds of MI, REFGUIDEUPPER=Higher Odds of MI);

Forest Plot from %MVMODELS macroForest Plot from %MVMODELS macro

 

 

 

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
PharmlyDoc
Quartz | Level 8

Though it's not the ideal method, and requires manual input of values and manipulation through datalines in the subgroup dataset, it works. 

 

data anno_label;
length function $10 anchor $20 drawspace $20;
function='text';
drawspace='GraphPercent';
x1=37; y1=15;
label= "<– Lower Odds of Infarct     Higher Odds of Infarct –>";
textcolor='gray77'; textsize=10;
width=100;
output;
x1=40; y1=12;
label= "Odds Ratios (log scale)";
output;
run;



/* Replace all missing values with blank   */
OPTIONS MISSING=" ";

proc sgplot data=SubgroupData_v2 noautolegend pad=(bottom=75)  sganno=anno_label ;
styleattrs backcolor=whitesmoke  ;  /* axisextent=data to remove borders  */
refline ref /  lineattrs=(thickness=15 color=aliceblue);
highlow y=row low=LCL high=UCL / lowcap=serif highcap=serif;
scatter y=row x=OR / markerattrs=(symbol=squarefilled color=royalblue);
scatter y=row x=OR / markerattrs=(size=0) x2axis;
refline  1  / axis=x lineattrs=(thickness=2 color=brbl ) ;
refline 0  5 / axis=x noclip;
Refline 0.5 / axis=x lineattrs=(pattern=shortdash) label;
Refline 1.5 / axis=x lineattrs=(pattern=shortdash) label;

yaxistable subgroup /  location=inside position=left 
  indentweight=indent ;

yaxistable OR LCL UCL pvalue / location=inside
position=right ; 
yaxis reverse  display=(nolabel noline noticks
novalues)   colorbands=odd colorbandsattrs=(color=aliceblue transparency=0.5)  ;

xaxis display=(nolabel)   values=(0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0)  type=log logstyle=logexpand   minor logbase=10  ;
x2axis  display=(nolabel noline noticks
novalues) ; 
run;

 

Screen Shot 2021-07-24 at 3.06.24 PM.png

 

 

View solution in original post

6 REPLIES 6
Reeza
Super User

Well, the author of the macro can probably answer this the fastest 🙂

Paging @JeffMeyers 

 

Personally, I suspect this falls outside enough it may be worth considering a different approach - for example creating a new variable that is the concatenated version and using that? It really depends on what you're trying to do overall.

 

This is another variation of code on a similar graph that may be easier for you to modify yourself. 

https://blogs.sas.com/content/graphicallyspeaking/2016/05/30/ctspedia-clinical-graphs-subgrouped-for...

 


@PharmlyDoc wrote:

 

The MVMODELS macro has some nice formatting capabilities for producing forest plots from a multivariable logistic regression. However I am unable to add interaction terms like I can with just running proc logistic.

https://communities.sas.com/t5/SAS-Communities-Library/MVMODELS-a-Macro-for-Survival-and-Logistic-An...

 

The macro code for MVMODELS exports parameterestimates from proc logistic, but I have limited expertise with macro coding. Is there a method to alter the MVMODEL code so that I can enter the interaction terms according to  sex*race or sex|race and have the MVMODEL plot the estimates as shown in the proc logistic forest plot but still be formatted as the MVMODEL forest plot?

If that makes sense.

 

I have an input dataset called infarct.

I ran proc logistic modeling infarct as event='1' (for some reason SAS gives me an error when I put event=1), and it gives me a forest plot with the interaction terms between Sex and Race.

 

Data infarct ;
infile datalines delimiter="," ;
input BBlocker Alcohol Smoking Sex $ Race :$9. Age BMI TG Cpeptide Glucose Infarct @@;
datalines;
0,1,0,F,non-white,78,19.3,1.1,0.4,6.6,1
0,1,0,M,white,72,24.6,2.3,1.9,8.6,1
0,0,0,M,non-white,61,25.2,0.7,4.1,5.7,0
0,1,1,M,non-white,62,24.9,1,3.9,8.7,1
0,1,1,F,non-white,55,23.4,2.1,2.5,6.2,0
0,0,0,M,white,51,24.8,0.9,6.6,9.1,0
0,0,0,F,non-white,65,22.2,1.6,0.7,15.1,0
0,1,0,M,white,71,27.7,2.2,2.4,5.7,0
0,1,1,M,white,64,26.4,2.2,0.6,11.2,1
0,0,0,M,non-white,56,27.8,1.2,1.3,6.8,0
0,1,1,F,non-white,54,30.9,2.1,0.9,3.8,0
0,0,0,M,white,71,21.9,0.8,2.3,7.7,0
0,0,1,F,non-white,57,21.2,1.8,1.5,8.2,0
0,0,0,M,non-white,64,27.7,1.4,1.1,13.9,0
0,1,0,F,white,76,26.6,1.6,1.5,7.2,1
0,0,0,F,white,77,26.7,1.4,4.7,8.8,0
0,0,0,F,non-white,63,26.8,1.1,1.7,7.6,0
0,0,0,M,white,74,30.7,1.6,2.3,10.8,0
0,1,0,M,white,65,22.2,1.3,0.6,11.8,1
0,0,0,M,white,83,23.4,1.2,1.8,17.2,0
0,1,0,F,white,59,24.5,1.4,2.3,10.7,1
0,1,0,M,non-white,57,23.7,0.6,2.5,6.9,1
0,1,0,F,non-white,73,18.6,1.3,1.5,9.2,1
0,1,1,M,white,74,32.2,1.7,1.9,8.4,1
0,0,0,F,non-white,48,26.3,1.2,1.7,8.3,0
0,0,0,F,white,55,21.2,2.1,1.7,13.6,0
0,1,0,F,non-white,66,30.3,0.8,3.4,6,0
0,0,1,F,white,52,29.8,0.7,4.5,4,0
0,1,0,M,white,56,26.9,1.6,1,10.6,1
0,0,0,M,white,74,23.6,2,2.1,8.3,0
1,1,1,F,white,61,22.3,2.1,2.4,10.1,0
1,1,1,M,non-white,69,25.4,2.4,1.3,11.2,1
1,1,0,F,non-white,60,29.3,2.5,1.5,11.8,1
1,1,1,M,white,55,34.5,3.4,0.8,10.8,1
1,0,0,M,non-white,57,25.9,0.6,2.5,6.6,0
1,0,0,M,non-white,67,35,1.2,2.1,8.2,1
1,1,0,M,non-white,43,26.8,1.7,1.2,10.4,1
1,1,0,M,white,63,32.1,2.5,3.1,4.3,0
1,0,0,M,white,68,26.3,1.5,3.2,10.8,0
1,1,1,M,non-white,65,34.1,4.1,0.9,8.3,1
1,0,0,F,non-white,47,23.4,1.7,1.5,6.8,0
1,1,0,F,non-white,50,28.6,2.3,2.5,11.9,1
1,1,1,F,non-white,53,28.6,1.3,2.5,10.7,0
1,0,0,F,non-white,65,32.2,0.6,2.3,9.7,0
1,1,1,M,non-white,68,26.1,0.6,2.3,5.7,0
1,0,0,M,non-white,53,26.7,0.6,2.5,8.3,0
1,1,0,M,non-white,60,31.2,1.9,1.9,7.2,1
1,0,0,M,non-white,59,33.2,1.1,2.9,16.7,0
1,1,1,F,non-white,57,28.1,3.9,2.7,8.7,1
1,0,0,M,white,59,23.9,2.5,1.9,13.6,0
1,1,1,M,non-white,69,25.7,0.9,0.8,10.6,1
1,1,0,M,white,59,23.5,7.4,1.9,13.9,0
1,0,1,F,non-white,67,29.6,2.1,5.1,11.9,1
1,1,0,F,non-white,66,32.6,2.3,6.1,6,0
1,1,0,F,white,58,27.8,0.9,1.7,9.1,0
1,0,1,M,non-white,54,33.9,1.8,1.7,8.4,1
1,0,0,F,white,64,24.4,1.9,2.4,9.1,0
1,1,0,F,white,52,27.5,2.3,2.3,10.9,1
1,1,0,F,white,48,27.4,2.9,1.7,7.7,1
1,1,0,F,non-white,62,32.3,4.7,2.1,8.8,1
1,1,1,F,non-white,50,25.9,2.4,1.1,20.7,1
1,0,1,M,white,56,24,1.7,4.5,10.6,0
1,1,0,M,non-white,70,24.5,4.5,0.8,15.1,1
1,0,0,F,white,58,35.7,1.5,3.2,17,0
1,1,0,F,non-white,62,29.6,1.1,3.4,8.4,0
1,0,0,F,non-white,62,27.4,1,4.7,8.6,0
1,1,0,F,non-white,68,30.3,1.5,3.9,9.2,1
1,1,0,F,white,53,29.5,0.7,2.4,9.2,0
1,0,1,F,non-white,68,29.7,1.5,1.8,11.2,1
1,1,0,F,non-white,62,25.7,2.4,4.1,10.8,1
1,1,1,F,non-white,58,29.8,0.6,1.1,7.6,0
;
run;

proc format;
value Infarctfmt 0 = "No"
1 = "Yes"
;
value BBlockerfmt 0 = "No"
1 = "Yes"
;
value Alcoholfmt 0 = "No"
1 = "Yes"
;
value Smokingfmt 0 = "No"
1 = "Yes"
;
run;

data infarct;
set infarct;
format infarct Infarctfmt.;
format alcohol Alcoholfmt.;
format BBlocker BBlockerfmt.;
format smoking Smokingfmt.;
run;

proc logistic data=infarct  plots(only)=(EFFECT ODDSRATIO(logbase=10   TYPE=HORIZONTALSTAT ));
class BBlocker(ref='No') Alcohol(ref='Yes') Smoking(ref='Yes') Sex(ref='M') Race(ref='non-white') /param=ref ;
model infarct(event='Yes')=  BBlocker Alcohol Smoking Sex|Race Age BMI TG Cpeptide Glucose /  orpvalue clodds=wald  lackfit;
oddsratio BBlocker /  cl=wald;
oddsratio Alcohol /  cl=wald;
oddsratio Smoking /  cl=wald;
oddsratio Sex / cl=wald;
oddsratio Race / cl=wald;
oddsratio Age / cl=wald;
oddsratio BMI / cl=wald;
oddsratio  TG / cl=wald;
oddsratio Cpeptide / cl=wald;
oddsratio Glucose / cl=wald;
run;
quit;

Forest Plot from proc logisticForest Plot from proc logistic

 

Code for MVMODEL (I've attached a modified version that adds the option for third reference line) does not allow me to enter interaction terms, but I like the way it's formatted and how the odds ratios and confidence intervals are limited to 2 decimal places:

 

%mvmodels (DATA=infarct, METHOD=LOGISTIC, NMODELS=1,
    EVENTCOV=infarct,EVENT=Yes,COVARIATES=BBlocker Alcohol Smoking Sex Race Age BMI TG Cpeptide Glucose, TYPE=2 2 2 2 2 1 1 1 1 1 ,
    CONT_DISPLAY=2, CAT_DISPLAY=4, cat_param=ref, cat_ref=No`Yes`Yes`M`non-white, 
    XAXISTYPE=log, LOGBASE=10, XAXISLABEL=Odds Ratios (log scale),
    PVAL_TYPE3=0, 
DISPLAY=subtitle or_plot or_est_range , show_adjcovariates=1, pval_covariates=1, refline=1,  SREFLINE=0.5, SREFLINEPATTERN=SHORTDASH, 
 TREFLINE=1.5, TREFLINEPATTERN=SHORTDASH, LOGTICKSTYLE = LOGEXPAND, LOGMINOR=TRUE, 
 LINECOLOR=blue, labels=Beta Blocker``Smoking Status```Age in years`BMI (%)`Triglycerides (mmol/L)`C-Peptide (nmol/L)`HbA1c (%),REFGUIDELOWER=Lower Odds of MI, REFGUIDEUPPER=Higher Odds of MI);

Forest Plot from %MVMODELS macroForest Plot from %MVMODELS macro

 

 

 

 

 

 

 


 

 

PharmlyDoc
Quartz | Level 8

I tried a different manual approach using sgplot and sganno, but I don't understand how to use dattrmap=attrmap, the text function, nor how to properly construct an annotation dataset that shows "Higher Odds of MI and Lower offs of MI" below the xaxis and centered at left and right around the refline=1, as well as put "Odds Ratios (log scale)" directly below. 

 

I ran proc logistic and outputted the oddsratioswald as ORwald; I then dropped the unit column; I then exported ORwald as a csv dataset; I then opened the ORwald.csv dataset in SAS and copied and pasted the values into an input statement; I then manually added an "ident" column at the beginning, went through each row and added 0 and 1 as appropriate, as well as added a "ref" column at the end in order to insert colorbands. 

 

 

ods output  oddsratioswald = ORwald;
proc logistic data=infarct  plots(only)=(ODDSRATIO(logbase=10   TYPE=HORIZONTALSTAT ));
class BBlocker(ref='No') Alcohol(ref='Yes') Smoking(ref='Yes') Sex(ref='M') Race(ref='non_white') /param=ref ;
model infarct(event='Yes')=  BBlocker Alcohol Smoking Sex|Race Age BMI TG Cpeptide Glucose /  orpvalue clodds=wald  lackfit;
oddsratio BBlocker /  cl=wald;
oddsratio Alcohol /  cl=wald;
oddsratio Smoking /  cl=wald;
oddsratio Sex / cl=wald;
oddsratio Race / cl=wald;
oddsratio Age / cl=wald;
oddsratio BMI / cl=wald;
oddsratio  TG / cl=wald;
oddsratio Cpeptide / cl=wald;
oddsratio Glucose / cl=wald;
run;
quit;
ods output close;


proc print data=orwald;
run;

proc sql;
alter table orwald
drop unit;
quit;

proc export data=orwald DBMS=csv   
outfile='oddsratioswald_infarct.csv';  
run; 

 

 

Effect,OddsRatioEst,LowerCL,UpperCL,pValue
BBlocker Yes vs No,0.701,0.114,4.309,0.7012
Alcohol No vs Yes,0.032,0.004,0.237,0.0007
Smoking No vs Yes,0.742,0.168,3.276,0.6939
Sex F vs M at Race=non_white,0.220,0.033,1.481,0.1197
Sex F vs M at Race=white,3.034,0.262,35.172,0.3746
Race white vs non_white at Sex=F,0.758,0.120,4.789,0.7686
Race white vs non_white at Sex=M,0.055,0.004,0.727,0.0277
Age,1.087,0.983,1.202,0.1039
BMI,1.142,0.924,1.412,0.2175
TG,1.513,0.698,3.277,0.2942
Cpeptide,0.629,0.326,1.215,0.1673
Glucose,1.279,0.993,1.647,0.0569

 

Also note that this is a fake dataset, and I changed the UCL for female at race=white from 35 to 3.5. I decided to use proc sgplot instead of sgrender+template because when attempting to create templates I kept getting errors with highlowplot and scatter plot statements. For the forest plot below, how do I construct an annotation dataset that shows "Higher Odds of MI and Lower offs of MI" below the xaxis and centered at left and right around the refline=1? As well as put "Odds Ratios (log scale)" directly below? (using sganno and not using the label option in the xaxis statement)

 

data Subgroup;
infile datalines dlm=",";
 input Indent Subgroup : $30. OR LCL UCL PValue : $9. ref;
 format OR LCL UCL 7.2 ;
 if OR ne . then do;


end;
 row = _n_;

datalines;
0,Age,1.087,0.983,1.202,0.1039,.
0,Beta-Blocker,.,.,.,.,2
1,No,.,.,.,reference,3
1,Yes,0.701,0.114,4.309,0.7012,4
0,Alcohol,.,.,.,.,.
1,Yes,.,.,.,reference,.
1,No,0.032,0.004,0.237,0.0007,.
0,Smoking,.,.,.,.,8
1,Yes,.,.,.,reference,9
1,No,0.742,0.168,3.276,0.6939,10
0,Sex,.,.,.,.,.
1,Male,.,.,.,reference,.
1,Female at Race=non-white,0.220,0.033,1.481,0.1197,.
1,Female at Race=white,3.034,0.262,3.5172,0.3746,.
0,Race,.,.,.,.,15
1,non-white,.,.,.,reference,16
1,white at Sex=Female,0.758,0.120,4.789,0.7686,17
1,white at Sex=M,0.055,0.004,0.727,0.0277,18
0,BMI,1.142,0.924,1.412,0.2175,.
0,Triglycerides,1.513,0.698,3.277,0.2942,20
0,C-peptide,0.629,0.326,1.215,0.1673,.
0,HbA1c,1.279,0.993,1.647,0.0569,22
;

/* Replace all missing values with blank   */
OPTIONS MISSING=" ";

proc sgplot data=Subgroup noautolegend pad=(bottom=75)  ;
styleattrs backcolor=whitesmoke  ;  /* axisextent=data to remove borders  */
refline ref /  lineattrs=(thickness=15 color=aliceblue);
highlow y=row low=LCL high=UCL / lowcap=serif highcap=serif;
scatter y=row x=OR / markerattrs=(symbol=squarefilled color=royalblue);
scatter y=row x=OR / markerattrs=(size=0) x2axis;
refline  1  / axis=x lineattrs=(thickness=2 color=brbl ) ;
refline 0  5 / axis=x noclip;
Refline 0.5 / axis=x lineattrs=(pattern=shortdash) label;
Refline 1.5 / axis=x lineattrs=(pattern=shortdash) label;


yaxistable subgroup /  location=inside position=left 
  indentweight=indent ;



yaxistable OR LCL UCL pvalue / location=inside
position=right ; 
yaxis reverse  display=(nolabel noline noticks
novalues)   colorbands=odd colorbandsattrs=(color=aliceblue transparency=0.5)  ;



xaxis  display=(nolabel) values=(0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0)  type=log logstyle=logexpand  logbase=10  ;
x2axis  display=(nolabel noline noticks
novalues); 
run;

proc sgplot: forest plotproc sgplot: forest plot



 

 

Reeza
Super User
The link I included above with the post has the full code at the bottom of the page that illustrates how to do all of this, is something in there not working for you?
PharmlyDoc
Quartz | Level 8

I tried that, but I had issues with formatting when I tried omitting the  count and percent columns. I also want the 

"PCI Better" and "Therapy Better" labels to be below the xaxis, not above, and then have a label of "Odds Ratios (log scale) centered  below them. I want to only use an annotation dataset for the labels below the xaxis. 

 

proc format;;
  value $txt
  "T" = "Therapy Better (*ESC*){Unicode '2192'x}"
  "P" = "(*ESC*){Unicode '2190'x} PCI Better";
run;

 Screen Shot 2021-07-23 at 10.25.02 AM copy.png

 

 

 

 

 

 

 

 

 

Mimicking the plot found at https://blogs.sas.com/content/graphicallyspeaking/2016/05/30/ctspedia-clinical-graphs-subgrouped-for... , I would want it to look like this (I used Adobe Illustrator to alter it):

 

Screen Shot 2021-07-23 at 11.53.05 AM.png

 

 

PharmlyDoc
Quartz | Level 8

Though it's not the ideal method, and requires manual input of values and manipulation through datalines in the subgroup dataset, it works. 

 

data anno_label;
length function $10 anchor $20 drawspace $20;
function='text';
drawspace='GraphPercent';
x1=37; y1=15;
label= "<– Lower Odds of Infarct     Higher Odds of Infarct –>";
textcolor='gray77'; textsize=10;
width=100;
output;
x1=40; y1=12;
label= "Odds Ratios (log scale)";
output;
run;



/* Replace all missing values with blank   */
OPTIONS MISSING=" ";

proc sgplot data=SubgroupData_v2 noautolegend pad=(bottom=75)  sganno=anno_label ;
styleattrs backcolor=whitesmoke  ;  /* axisextent=data to remove borders  */
refline ref /  lineattrs=(thickness=15 color=aliceblue);
highlow y=row low=LCL high=UCL / lowcap=serif highcap=serif;
scatter y=row x=OR / markerattrs=(symbol=squarefilled color=royalblue);
scatter y=row x=OR / markerattrs=(size=0) x2axis;
refline  1  / axis=x lineattrs=(thickness=2 color=brbl ) ;
refline 0  5 / axis=x noclip;
Refline 0.5 / axis=x lineattrs=(pattern=shortdash) label;
Refline 1.5 / axis=x lineattrs=(pattern=shortdash) label;

yaxistable subgroup /  location=inside position=left 
  indentweight=indent ;

yaxistable OR LCL UCL pvalue / location=inside
position=right ; 
yaxis reverse  display=(nolabel noline noticks
novalues)   colorbands=odd colorbandsattrs=(color=aliceblue transparency=0.5)  ;

xaxis display=(nolabel)   values=(0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0)  type=log logstyle=logexpand   minor logbase=10  ;
x2axis  display=(nolabel noline noticks
novalues) ; 
run;

 

Screen Shot 2021-07-24 at 3.06.24 PM.png

 

 

JeffMeyers
Barite | Level 11
Hello,
The macro can run interaction models, but can only output the p-value from the interaction term from the model. There are too many ways to display interaction models, so the macro focuses instead on being able to do subgroup analyses of interest.

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
  • 1026 views
  • 2 likes
  • 3 in conversation