Introduction

An Odds Ratio (OR) is a powerful statistic used in medical and epidemiological research to measure the strength of association between an exposure (like smoking) and an outcome (like lung cancer).

To truly understand an Odds Ratio, we first need to look at what “Odds” mean for individual groups. Unlike probability (which looks at cases out of the total population), Odds compare the number of people who get a disease directly to the number of people who do not.

Setting Up Our Contingency Table

Let’s create a hypothetical dataset of 180 participants: * Smokers: 50 developed lung cancer, 10 did not. * Non-Smokers: 30 developed lung cancer, 90 did not.

# Constructing the 2x2 matrix
cancer_table <- matrix(c(50, 10,   # Row 1: Smoker (Yes, No)
                         30, 90),  # Row 2: Non-Smoker (Yes, No)
                       nrow = 2, byrow = TRUE,
                       dimnames = list(Smoking_Status = c("Smoker", "Non-Smoker"), 
                                       Lung_Cancer = c("Yes", "No")))

print(cancer_table)
##               Lung_Cancer
## Smoking_Status Yes No
##     Smoker      50 10
##     Non-Smoker  30 90

Calculating and Interpreting Group Odds

Let’s extract the exact odds for each independent group by dividing the “Yes” cases by the “No” cases.

#Odds for Smokers
smoker_odds <- cancer_table["Smoker", "Yes"] / cancer_table["Smoker", "No"]

#Odds for Non-Smokers
non_smoker_odds <- cancer_table["Non-Smoker", "Yes"] / cancer_table["Non-Smoker", "No"]

cat("Odds for Smokers:", smoker_odds, "\n")
## Odds for Smokers: 5
cat("Odds for Non-Smokers:", round(non_smoker_odds, 4), "\n")
## Odds for Non-Smokers: 0.3333

What do these numbers actually mean?

  • Smoker Odds = 5: This means that for every 1 smoker who stays cancer-free, 5 smokers will develop lung cancer. In this group, getting the disease is 5 times more likely than not getting it.
  • Non-Smoker Odds = 0.333 (or 1/3): This means that for every 3 non-smokers who stay cancer-free, only 1 non-smoker will develop lung cancer. In this group, getting the disease is 3 times less likely than staying healthy.

Finding the Odds Ratio (OR)

The Odds Ratio simply divides the odds of our exposed group (Smokers) by the odds of our reference group (Non-Smokers).

We can compute this automatically using the epitools package. We use rev = "rows" to ensure R treats “Non-Smoker” as our baseline comparison group.

# Load the library (make sure to install.packages("epitools") first if needed)
library(epitools)

or_analysis <- oddsratio(cancer_table, rev = "both", method = "wald")
# Note on how epitools works:
# By default, the oddsratio() function expects a strict epidemiology layout:
#   - Row 1 must be the UNEXPOSED group (Baseline / Reference)
#   - Column 1 must be the HEALTHY outcome (No Disease)
# Because our table was built with "Smoker" first and "Yes (Cancer)" first,the default calculation gets flipped upside down. 
# Setting rev = "both" fixes this by telling R to:
#   1. Flip the rows: Moves "Non-Smoker" to Row 1 to act as the baseline reference (1.0).
#   2. Flip the columns: Moves "No" (Healthy) to Column 1 so R tracks the risk of getting sick.
# This ensures R calculates the true risk of smoking (OR = 15) instead of the inverse (0.066).

# The method = "wald" argument tells the epitools package to use the Wald test method to calculate the 95% Confidence Intervals (CI) and p-value for your Odds Ratio.

# It Assumes a Normal DistributionThe Wald method transforms your odds ratio into a natural logarithm (\(\ln(OR)\)). In statistics, this transformation creates a symmetrical, bell-shaped normal curve. The function calculates the standard error on this log scale, builds the interval, and then converts it back (exponentiates it) to give you your lower and upper bounds.
print(or_analysis$measure)
##               odds ratio with 95% C.I.
## Smoking_Status estimate    lower    upper
##     Non-Smoker        1       NA       NA
##     Smoker           15 6.775075 33.20996

Replicating with Logistic Regression (glm)

In professional data analysis, we usually calculate this via a logistic regression model. This yields the exact same calculation:

# Creating an individual-level data frame mirroring the table above
study_data <- data.frame(
  Smoking_Status = factor(c(rep("Smoker", 60), rep("Non-Smoker", 120)), 
                          levels = c("Non-Smoker", "Smoker")), 
  Lung_Cancer = factor(c(rep("Yes", 50), rep("No", 10),    
                         rep("Yes", 30), rep("No", 90)),   
                       levels = c("No", "Yes"))            
)

#levels = c("Non-Smoker", "Smoker") forces R to use Non-Smokers as the baseline comparison group.

#levels = c("No", "Yes"): This forces R to use No Cancer as the baseline health state.

# Fit model and exponentiate the coefficients
model <- glm(Lung_Cancer ~ Smoking_Status, data = study_data, family = binomial)
print(exp(coef(model)))
##          (Intercept) Smoking_StatusSmoker 
##            0.3333333           15.0000000

Final Interpretation Summary

\[\text{Odds Ratio} = \frac{\text{Smoker Odds}}{\text{Non-Smoker Odds}} = \frac{5.0}{0.333} = 15.0\]

Conclusion: Our final Odds Ratio is 15. This tells us that individuals who smoke have 15 times the odds of developing lung cancer compared to individuals who do not smoke.