Showing posts with label categorical data. Show all posts
Showing posts with label categorical data. Show all posts

Monday, March 7, 2011

Example 8.29: Risk ratios and odds ratios



When can you safely think of an odds ratio as being similar to a risk ratio?

Many people find odds ratios hard to interpret, and thus would prefer to have risk ratios. In response to this, you can find several papers that purport to convert an odds ratio (from a logistic regression) into a risk ratio.

Conventional wisdom has it that "odds ratios can be interpreted as risk ratios, as long as the event is rare." Is this true? To what degree?

Let's write a function to examine what the risk ratio is for a given odds ratio. To concretize slightly, suppose we're examining the odds ratio and risk ratio of a "case" given the presence or absence of an "exposure." For a given odds ratio, the risk ratio will vary depending on the baseline probability (the probability of a case in the absence of the exposure). So we'll make the output a plot with the baseline probability as the x-axis. To aid interpretation, we'll add vertical reference lines at baseline probabilities with default placement at 0.1 and 0.2-- two values that we might think of as small enough to be able to interpret the odds ratio as a risk ratio.

SAS

In SAS, we'll write a macro to generate the plot. First, we need to calculate the odds when the exposure is absent, then the odds when it is present (using the designated odds ratio), the probability implied by this exposed odds (for when the exposure is present), and finally the risk ratio. The coding is nothing special, with the possible exception of the loop through the base probabilities (see section 1.11.1).


%macro orvsrr(OR=2,ref1=.1,ref2=.2);
data matt;
do p_base = 0.001, .01 to .99 by 0.01, .999;
odds_base = p_base/(1-p_base);
odds_case = &or * odds_base;
p_case = odds_case / (1 + odds_case);
RR = p_case/p_base;
output;
end;
run;

title "RR if OR = &or by base probability";
symbol1 i = j l = 1 c = blue v = none;
proc gplot data = matt;
plot RR * p_base / href = &ref1, &ref2;
label p_base = "Probability in reference group" RR = "Risk ratio";
run; quit;
%mend orvsrr;

The result of %orvsrr(3,.05,.1); is shown above.

R

In R, the function to replicate this is remarkably similar. In fact, the calculation of the odds, probabilities, and risk ratio is identical with the SAS version. The c() and seq functions replace the do loop used in SAS.


orvsrr = function (or=2, ref1=.1, ref2=.2) {
p_base = c(.001, seq(.01,.99, by = .01), .999)
odds_base = p_base/(1-p_base)
odds_case = or * odds_base
p_case = odds_case / (1 + odds_case)
RR = p_case/p_base

plot(p_base, RR, xlim=c(0, 1), ylim=c(1, or), xaxs="i", yaxs="i",
xlab="Probability in reference group", ylab="Risk ratio", type = "n")
title(main = paste("RR if OR =", or, "by base probability"))
lines(p_base, RR, col="blue")
abline(v=c(ref1, ref2))
}

The result of orvsrr(2.5,.1,.3) is shown below.

The conventional wisdom is correct, up to a point, as you can find by playing with the function or the macro. If the baseline probability is very low (less than 0.05) and the odds ratio is smallish (less than 3 or so) then the odds ratio overestimates the risk ratio by 10% or less. Larger odds ratios or baseline probabilities result in greater overestimation of the risk ratio.

Monday, December 14, 2009

Example 7.18: Displaying missing value categories in a table

When displaying contingency tables (section 2.3.1), there are times when it is useful to either show or hide the missing data category. Both SAS and the typical R command default to displaying the table only for observations where both factors are observed.

In this example, we generate some multinomial data (section 1.10.4) and then produce tables with and without missing data categories.

SAS

Generate the multinomial data, uniform data, and use the latter to censor the former:

data blog;
do i = 1 to 300;
x = rand("TABLE",.3,.4);
y = rand("TABLE",.3,.4);
if uniform(0) gt .8 then x = .;
if uniform(0) gt .8 then y = .;
output;
end;
run;


Print the default table with only complete data. Note the options used to reduce output, as in section 4.6.9.

proc freq data=blog;
tables y*x / norow nocol;
run;


This produces:

Table of y by x

y x

Frequency|
Percent | 1| 2| 3| Total
---------+--------+--------+--------+
1 | 16 | 13 | 18 | 47
| 8.16 | 6.63 | 9.18 | 23.98
---------+--------+--------+--------+
2 | 18 | 32 | 22 | 72
| 9.18 | 16.33 | 11.22 | 36.73
---------+--------+--------+--------+
3 | 28 | 31 | 18 | 77
| 14.29 | 15.82 | 9.18 | 39.29
---------+--------+--------+--------+
Total 62 76 58 196
31.63 38.78 29.59 100.00

Frequency Missing = 104


The missing categories are included through the missprint option.

proc freq data = blog;
tables y*x / norow nocol missprint;
run;


This produces:

Table of y by x

y x

Frequency|
Percent | .| 1| 2| 3| Total
---------+--------+--------+--------+--------+
. | 12 | 12 | 20 | 14 | .
| . | . | . | . | .
---------+--------+--------+--------+--------+
1 | 10 | 16 | 13 | 18 | 47
| . | 8.16 | 6.63 | 9.18 | 23.98
---------+--------+--------+--------+--------+
2 | 17 | 18 | 32 | 22 | 72
| . | 9.18 | 16.33 | 11.22 | 36.73
---------+--------+--------+--------+--------+
3 | 19 | 28 | 31 | 18 | 77
| . | 14.29 | 15.82 | 9.18 | 39.29
---------+--------+--------+--------+--------+
Total . 62 76 58 196
. 31.63 38.78 29.59 100.00
Frequency Missing = 104


Note that if there are no missing values, SAS will not print the rows and columns headed with a '.' which is analogous to the "ifany" option in R shown below.

R

First, generate the data:

library(Hmisc)
x <- rMultinom(matrix(c(.3,.3,.4),1,3),300)
y <- rMultinom(matrix(c(.3,.3,.4),1,3),300)


Then, generate some random Uniforms to censor some of the observed data:

censprobx <- runif(300)
censproby <- runif(300)


Censor the data:

x[censprobx > .8] <- NA
y[censproby > .8] <- NA


Produce the default table (omits any missing data):

table(y,x)

x
y 1 2 3
1 18 18 29
2 17 21 22
3 20 30 40


Make the table which includes the missing category:

table(y, x, useNA="ifany")

x
y 1 2 3 NA
1 18 18 29 9
2 17 21 22 17
3 20 30 40 17
NA 14 5 14 9


The useNA option also allows the values "no" and "always". The value "no" corresponds to the default behavior in R or SAS, while the "always" option is not available in SAS. SAS, however, shows the total number missing in any case.