Hi,
I'm using PROC FREQ to calculate an odds ratio. I'm able to get a 95% CI but how can I get the p-value?
I understand that if i look at the CI and if it includes 1, it's not significant, but I'd like to include the actual p-value.
Thanks.
proc freq data = test ;
tables var1*var2 / relrisk alpha=0.05;
run;
Hi @sharonlee,
I found SAS Usage Note 53376 helpful for this task and have put together an example showing three different ways to obtain the p-value (for a two-sided Wald test of H0: odds ratio=1 at alpha=0.05, consistent with the corresponding confidence interval):
/* Create test data */
data test;
n11=10; n12=8; n21=58; /* n21=59; */ n22=16;
do _n_=1 to n11; c=1; r=1; output; end;
do _n_=1 to n12; c=1; r=2; output; end;
do _n_=1 to n21; c=2; r=1; output; end;
do _n_=1 to n22; c=2; r=2; output; end;
run;
/* Odds ratio with Wald confidence interval, but without p-value */
ods output relativerisks=rr(where=(statistic=:'O'));
proc freq data=test;
tables c*r / relrisk alpha=0.05;
run;
proc print data=rr;
var _numeric_;
format _numeric_ best16.;
run;
/* Ditto including p-value */
ods select none;
ods select diffs;
ods output diffs=odd;
proc logistic data=test;
class c / param=glm;
model r=c;
lsmeans c / diff oddsratio cl;
run;
ods select all;
proc print data=odd;
var OddsRatio--upperOR Probz;
format _numeric_ best16.;
run;
/* Same using new ORPVALUE option (requires SAS 9.4M3 or later) */
ods select none;
ods select cloddswald;
ods output cloddswald=odc;
proc logistic data=test;
class c / param=glm;
model r=c / clodds=wald orpvalue;
run;
ods select all;
proc print data=odc(drop=unit);
var _numeric_;
format _numeric_ best16.;
run;
/* Alternative: manual calculation */
data orp;
set test(obs=1);
z=probit(0.975);
v=1/n11+1/n12+1/n21+1/n22;
odr=n11*n22/n12/n21;
lcl=odr*exp(-z*sqrt(v));
ucl=odr*exp(z*sqrt(v));
p=1-probchi(log(odr)**2/v,1);
format odr lcl ucl oddsr8.3 p pvalue.;
run;
proc print data=orp(keep=odr--p);
format _all_ best16.;
run;
As you'll notice, there are minor differences (<1E-7, hence irrelevant, I'd say) between the values computed by PROC LOGISTIC on the one hand and the (slightly more accurate) values computed by PROC FREQ or the last data step on the other hand, maybe due to the model building process (PROC LOGISTIC). By using n21=59 (see first data step) you can switch to a situation where the test is significant.
Hi Chris,
Thanks for sharing this post with me. It seems the Breslow-Day test is computed if there is a third variable. In my case I only have two variables.
Hi @sharonlee,
I found SAS Usage Note 53376 helpful for this task and have put together an example showing three different ways to obtain the p-value (for a two-sided Wald test of H0: odds ratio=1 at alpha=0.05, consistent with the corresponding confidence interval):
/* Create test data */
data test;
n11=10; n12=8; n21=58; /* n21=59; */ n22=16;
do _n_=1 to n11; c=1; r=1; output; end;
do _n_=1 to n12; c=1; r=2; output; end;
do _n_=1 to n21; c=2; r=1; output; end;
do _n_=1 to n22; c=2; r=2; output; end;
run;
/* Odds ratio with Wald confidence interval, but without p-value */
ods output relativerisks=rr(where=(statistic=:'O'));
proc freq data=test;
tables c*r / relrisk alpha=0.05;
run;
proc print data=rr;
var _numeric_;
format _numeric_ best16.;
run;
/* Ditto including p-value */
ods select none;
ods select diffs;
ods output diffs=odd;
proc logistic data=test;
class c / param=glm;
model r=c;
lsmeans c / diff oddsratio cl;
run;
ods select all;
proc print data=odd;
var OddsRatio--upperOR Probz;
format _numeric_ best16.;
run;
/* Same using new ORPVALUE option (requires SAS 9.4M3 or later) */
ods select none;
ods select cloddswald;
ods output cloddswald=odc;
proc logistic data=test;
class c / param=glm;
model r=c / clodds=wald orpvalue;
run;
ods select all;
proc print data=odc(drop=unit);
var _numeric_;
format _numeric_ best16.;
run;
/* Alternative: manual calculation */
data orp;
set test(obs=1);
z=probit(0.975);
v=1/n11+1/n12+1/n21+1/n22;
odr=n11*n22/n12/n21;
lcl=odr*exp(-z*sqrt(v));
ucl=odr*exp(z*sqrt(v));
p=1-probchi(log(odr)**2/v,1);
format odr lcl ucl oddsr8.3 p pvalue.;
run;
proc print data=orp(keep=odr--p);
format _all_ best16.;
run;
As you'll notice, there are minor differences (<1E-7, hence irrelevant, I'd say) between the values computed by PROC LOGISTIC on the one hand and the (slightly more accurate) values computed by PROC FREQ or the last data step on the other hand, maybe due to the model building process (PROC LOGISTIC). By using n21=59 (see first data step) you can switch to a situation where the test is significant.
This was very helpful!!! Thank you for taking the time to respond to my question. It saved me lots of time and energy.
@sharonlee wrote:
Hi,
I'm using PROC FREQ to calculate an odds ratio. I'm able to get a 95% CI but how can I get the p-value?
I understand that if i look at the CI and if it includes 1, it's not significant, but I'd like to include the actual p-value.
Thanks.
p_values only exist in relationship to a test. I don't see a test requested. As an example this an equivalence test
proc freq data = test ; tables var1*var2 / relrisk (method=wald equiv) alpha=0.05; run;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
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.
Select SAS Training centers are offering in-person courses. View upcoming courses for: