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

Is there a way I can report odds ratio comparing 2 points for a GAM model?

 

proc gampl data=mydata;
   class gender / param=ref;
   model response(event='1') = gender spline(age)  / dist=binary link=logit;
run;

  For eg, is there a way, I can report OR at say  age=65 to age=75?   I know that R has an package, oddsratio specifically for GAM to get such odds ratios.  How can we replicate something similar in SAS?

1 ACCEPTED SOLUTION

Accepted Solutions
Ksharp
Super User

If I understood @StatDave  's code ,you can report OR at age=65 to age=75 .

a.k.a  OR= odds(age=65)/odds(age=75)

 

data have;
 set sashelp.heart(obs=1000 keep=status sex ageatstart rename=(ageatstart=age sex=gender));
run;

data test;
gender='Male';age=65;output;
gender='Male';age=75;output;
run;



data mydata;
 set have test indsname=indsname;
 dsn=indsname;
run;
proc gampl data=mydata;
   class gender / param=ref;
   id dsn;
   model status= param(gender) spline(age)  / dist=binary link=logit;
   output out=out xbeta=logodds;
   run;
proc transpose data=out(where=(dsn='WORK.TEST')) out=logodds;
run;
proc report data=logodds nowd split='*';
column col1 col2 or;
define col1/display 'log(odds) for age=65';
define col2/display 'log(odds) for age=75';
define or/computed 'OR=odds(age=65)/odds(age=75)';
compute or;
 or=exp(col1-col2);
endcomp;
run;

Ksharp_0-1770793276402.png

 

NOTE: as @StatDave  indicated the Male and Female have the same OR since model did not include interact effect “gender*age” . You can test it with the following data. Thanks Dave.

data test;
/*gender='Male  ';age=65;output;*/
/*gender='Male  ';age=75;output;*/
gender='Female';age=65;output;
gender='Female';age=75;output;
run;

View solution in original post

15 REPLIES 15
Ksharp
Super User
Since you are asking OR for a SPLINE effect(a.k.a a non-linear effect), that is not easy to get it.
I think you need help from macro %margin , %nlmeans:
https://support.sas.com/kb/35/189.html
PamG
Quartz | Level 8

You cannot write contrasts in PROC GAM or PROC GAMPL.  Is there a workaround this? This is easily achieved in R for GAM models.

Ksharp
Super User
It is a nonparametric regression unlike logistic model.
Maybe @Rick_SAS could give you a hand .
StatDave
SAS Super FREQ

You can fit a Generalized Additive logistic model to a binary response and obtain odds ratio estimates using the EFFECT statement in PROC LOGISTIC. The EFFECT statement creates the spline effect that you can use in the model. See the example in this note. In addition to the ODDSRATIO statement, you'll use the UNITS statement to specify the interval size that you want. For example

proc logistic data=mydata;
   effect spla=spline(age/naturalcubic basis=tpf(noint));
   class gender / param=ref;
   model response(event='1') = gender spla;
   oddsratio age / at(age=65);
   units age=10;
   run;

 

PamG
Quartz | Level 8

This is not a GAM model.  I need to fit a GAM and not a GLM model.

StatDave
SAS Super FREQ
With the addition of a spline term, the model fit in PROC LOGISTIC is indeed a GAM. See the description of GAMs, and the distinction with GLMs, in the Details:Generalized Additive Models section of the GAMPL procedure documentation. So, the only real difference is not the model type, but rather the fitting algorithm and details of how the spline is formed. But for practical purposes, they both fit a model allowing for an arbitrary amount of flexibility for the splined variable. And, of course, you can easily obtain odds ratios or other statistics available with PROC LOGISTIC.
PamG
Quartz | Level 8

GAM uses penalized likelihood with a penalty term for smoothing which is missing in GLM.  For the outcomes we deal with, GAM gives the best fit for such types of data.  I am aware of how it is done in SAS and getting contrasts for the spline effects but at this point what I am looking for is a solution using PROC GAM. 

StatDave
SAS Super FREQ

If you have to use PROC GAMPL then you could compute the odds ratio from the predicted log odds values, which are available with the XBETA= option in the OUTPUT statement when fitting a logistic model. For example, these statements compute the odds ratio for a one unit (year) increase in age from 65 to 66 in the Neuralgia data as seen in an example in the PROC LOGISTIC documentation. Since a spline is used, the odds ratio estimate will differ depending at which age it is computed. The values in the DATA step are the estimated log odds for a 66 year old male and a 65 year old male. The exponentiated difference in the log odds is the odds ratio for a unit (year) increase in age.

proc gampl data=neuralgia;
   class sex; id sex age;
   model pain(event='No') = param(sex) spline(age) / dist=binomial;
   output out=outg xbeta=logodds;
   run;
data _null_; or=exp(0.4048343234-0.5202755281); put or=; run;
Ksharp
Super User

If I understood @StatDave  's code ,you can report OR at age=65 to age=75 .

a.k.a  OR= odds(age=65)/odds(age=75)

 

data have;
 set sashelp.heart(obs=1000 keep=status sex ageatstart rename=(ageatstart=age sex=gender));
run;

data test;
gender='Male';age=65;output;
gender='Male';age=75;output;
run;



data mydata;
 set have test indsname=indsname;
 dsn=indsname;
run;
proc gampl data=mydata;
   class gender / param=ref;
   id dsn;
   model status= param(gender) spline(age)  / dist=binary link=logit;
   output out=out xbeta=logodds;
   run;
proc transpose data=out(where=(dsn='WORK.TEST')) out=logodds;
run;
proc report data=logodds nowd split='*';
column col1 col2 or;
define col1/display 'log(odds) for age=65';
define col2/display 'log(odds) for age=75';
define or/computed 'OR=odds(age=65)/odds(age=75)';
compute or;
 or=exp(col1-col2);
endcomp;
run;

Ksharp_0-1770793276402.png

 

NOTE: as @StatDave  indicated the Male and Female have the same OR since model did not include interact effect “gender*age” . You can test it with the following data. Thanks Dave.

data test;
/*gender='Male  ';age=65;output;*/
/*gender='Male  ';age=75;output;*/
gender='Female';age=65;output;
gender='Female';age=75;output;
run;
StatDave
SAS Super FREQ

Since gender does not interact with the age spline, the odds ratio estimate applies to both genders.

Ksharp
Super User
Thanks
PamG
Quartz | Level 8

Thank you @Ksharp !!! This is awesome and an interesting way of getting the ORs.

How would you write it if spline(age) and sex were interacting?  Basically if I had to use PROC LOGISTIC, can I use the same code to get effect for Age 45 vs 55 for males?  Also if I had to get the ORs for say 10 different time points, 45,47,48..etc vs 55, is there a way to write  a macro in the Proc report to repeat the calculations for many time points?

 

I wonder if I should start a new thread. 

PamG
Quartz | Level 8

If I use ESTIMATE then I do not get the same answers. I am not doing something right.

proc logistic data=mydata;
   class gender / param=ref;
   effect splage=spline(age/ basis=tpf knotmethod=equal(3));
   id dsn; 
   model status= gender splage gender*splage ;
 estimate 'For M: 45 vs 50(ref)' gender 2 splage[1,45][-1,50] gender*splage [1,2 45] [-1,2 50] / E EXP CL;
   output out=out xbeta=logodds;
   run;

proc transpose data=out(where=(dsn='WORK.TEST')) out=logodds;
run;

proc report data=logodds nowd split='*';
column col1 col2 or;
define col1/display 'log(odds) for age=45';
define col2/display 'log(odds) for age=50';
define or/computed 'OR=odds(age=45)/odds(age=50)';
compute or;
 or=exp(col1-col2);
endcomp;
run;
Ksharp
Super User

If I am using @StatDave  's code, I could get the same OR.

Check this:

1) Main Effect  --> Same OR

data have;
 set sashelp.heart(obs=1000 keep=status sex ageatstart rename=(ageatstart=age sex=gender));
run;

data test;
gender='Male';age=65;output;
gender='Male';age=75;output;
run;



data mydata;
 set have test indsname=indsname;
 dsn=indsname;
run;
proc logistic data=mydata;
   class gender / param=ref;
   effect spla=spline(age/naturalcubic basis=tpf(noint));
   model status= gender spla  ;
      oddsratio age / at(age=65);
      units age=10;

/* estimate 'For M: 45 vs 50(ref)' gender 2 splage[1,45][-1,50] gender*splage [1,2 45] [-1,2 50] / E EXP CL;*/
   output out=out xbeta=logodds;
   run;

proc transpose data=out(where=(dsn='WORK.TEST')) out=logodds;
var logodds;
run;
proc report data=logodds nowd split='*';
column col1 col2 or;
define col1/display 'log(odds) for age=65';
define col2/display 'log(odds) for age=75';
define or/computed 'when gender="Male"*OR=odds(age=75)/odds(age=65)';
compute or;
 or=exp(col2-col1);
endcomp;
run;

Ksharp_0-1770878542213.png

 

Ksharp_1-1770878569736.png

 

 

2) Interact Effect --> Also same OR

proc logistic data=mydata;
   class gender / param=ref;
   effect spla=spline(age/naturalcubic basis=tpf(noint));
   model status= gender spla  gender*spla;
      oddsratio age / at(age=65);
      units age=10;

/* estimate 'For M: 45 vs 50(ref)' gender 2 splage[1,45][-1,50] gender*splage [1,2 45] [-1,2 50] / E EXP CL;*/
   output out=out xbeta=logodds;
   run;

Ksharp_2-1770878865042.png

Ksharp_3-1770878884643.png

 

 

Catch up on SAS Innovate 2026

Nearly 200 sessions are now available on demand with the SAS Innovate Digital Pass.

Explore Now →
What is ANOVA?

ANOVA, or Analysis Of Variance, is used to compare the averages or means of two or more populations to better understand how they differ. Watch this tutorial for more.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 15 replies
  • 1358 views
  • 4 likes
  • 3 in conversation