11 Fisher’s exact test for sparse contingency tables

Each active treatment is compared separately with Control.

tab_A <- with(droplevels(subset(dat,treatment_arm %in% c("Control","Drug_A"))),
              table(Treatment=treatment_arm,Adverse_event=adverse_event_12w))
tab_B <- with(droplevels(subset(dat,treatment_arm %in% c("Control","Drug_B"))),
              table(Treatment=treatment_arm,Adverse_event=adverse_event_12w))

A <- as.data.frame.matrix(tab_A) |> tibble::rownames_to_column("Treatment")
B <- as.data.frame.matrix(tab_B) |> tibble::rownames_to_column("Treatment")
names(A) <- names(B) <- c("Treatment","No","Yes")

knitr::kables(list(
  kbl(A, caption="Drug_A versus Control"),
  kbl(B, caption="Drug_B versus Control")
))
Table 11.1: Drug_A versus Control
Treatment No Yes
Control 115 5
Drug_A 110 10
Table 11.1: Drug_B versus Control
Treatment No Yes
Control 115 5
Drug_B 98 22
ft_A <- fisher.test(tab_A)
ft_B <- fisher.test(tab_B)

tibble(
  comparison=c("Drug_A vs Control","Drug_B vs Control"),
  odds_ratio=c(unname(ft_A$estimate),unname(ft_B$estimate)),
  p_value=c(ft_A$p.value,ft_B$p.value),
  p_holm=p.adjust(c(ft_A$p.value,ft_B$p.value),method="holm")
) |> kbl(digits=3, caption="Fisher exact test results")
Table 11.2: Fisher exact test results
comparison odds_ratio p_value p_holm
Drug_A vs Control 2.085 0.286 0.286
Drug_B vs Control 5.131 0.001 0.002

Fisher’s exact test is performed separately for Drug_A versus Control and Drug_B versus Control. Holm adjustment accounts for the two comparisons.