← All notes

Statistical note

Contingency tables, risk, and exact tests

Chi-square independence, Fisher’s exact test, odds ratios, relative risk, and cell-count case studies.

9 min read

For counts OijO_{ij} in a contingency table, independence implies expected counts

Eij=(row totali)(column totalj)grand total,E_{ij}=\frac{(\text{row total}_i)(\text{column total}_j)}{\text{grand total}},

and Pearson’s statistic is χ2=ij(OijEij)2/Eij\chi^2=\sum_{ij}(O_{ij}-E_{ij})^2/E_{ij}.

Two-by-two counts, risks, and odds

import numpy as np
from scipy import stats
from scipy.stats.contingency import odds_ratio, relative_risk

table = np.array([[34, 16], [22, 28]])  # rows: treatment/control; cols: bound/unbound
print(stats.chi2_contingency(table))
print(stats.fisher_exact(table))
print(odds_ratio(table).statistic)
print(relative_risk(34, 50, 22, 50).relative_risk)

Case study: bacteriophage binding

The risk ratio compares binding probabilities; the odds ratio compares odds. They are not interchangeable when outcomes are common. Fisher’s exact test is useful for sparse 2×22\times2 tables; chi-square approximations require adequate expected counts.

The experimental unit remains the biological replicate, not every detected particle if particles share an acquisition context.

Functions: scipy.stats.chi2_contingency, fisher_exact, barnard_exact, boschloo_exact, odds_ratio, and relative_risk.