Atlas
statminds
CorrelationThe underlying model family class (e.g. GLM, linear model, categorical matrix, log-linear).Parametric ReferenceStatistical methods that assume a specific probability distribution family (typically normal).12-stage workflow

Contingency Coefficient (C)

Alternative categorical association measure from chi-square; ranges 0 to <1 with upper bound depending on table size.

Model familyCorrelation
Hypothesisnon-directional
AliasesPearson's C · Contingency Coefficient C · Adjusted Contingency Coefficient C*
G1
association
G2
effect_size
G3
description
1

What is it?

Contingency Coefficient (C) measures the strength of association between two nominal categorical variables within a multi-row and multi-column contingency table.

2

When to use it

  • R x C Tables: Tables larger than 2x2 (e.g. 3x3, 4x3) mapping categorical data.
  • Nominal Scales: Variables representing unordered categories (e.g., job sector vs. city).
3

Core Idea

Both indices scale nominal associations from 0 (complete independence) to 1 (perfect association). Perfect association means cell counts gather entirely on diagonal lines:

Diagonal concentration = Association
4

Hypotheses

H₀: No association exists (variables are independent)
Hₐ: Significant categorical association is present
5

How it works

  1. Compute Expected Frequencies for each cell based on marginal sums.
  2. Calculate Pearson Chi-Square (Chi-Square).
  3. Extract Cramer's V (V) or Contingency Coefficient (C) scaling factor.
  4. Test using Chi-Square distribution with df = (R - 1)(C - 1).
6

Assumptions

👤 Independence: Each case is in exactly one cell.
📊 Expected minimum: No cell should have expected count < 1; no more than 20% < 5.
7

Important Note

💡 Contingency Limit: The Contingency Coefficient C can never reach a perfect 1.00 even under perfect association (maximum possible is sqrt((k-1)/k) where k is number of cells). Cramer's V has no such ceiling limit.

8

Quick Example

Job SectorCity ACity B
Tech4512
Finance2035
Interactive Sandbox

Contingency Coefficient (C) Laboratory

Change the association strength to see how cell densities shift and drive the chi-square statistic.

Presets
Association Shift0.40
Sample Size (N)90
Subject Dot Density (3x3 Grid Space)Cell dots cluster diagonally as association strength increases
Contingency Frequencies
Row / ColCol 1Col 2Col 3
Row 11866
Row 26186
Row 36618
Calculated Score0.4924
Chi-Square (χ^2)28.80 (df=4)
p-value< 0.001
Statistical Verdict
✅ Reject H₀ (Significant)
Categorical distribution deviates significantly from random (Score = 0.49, p = < 0.001).
01Hypothesis test logic

Hypotheses

Pragmatic null and alternative hypotheses defined in mathematical notation.

A hypothesis is a question sharpened to a point. Ambiguity is the enemy of inference.
Logic Core
Null · H₀

H₀: C = 0 (no association between categorical variables)

Alternative · Hₐ

Hₐ: C > 0 (association exists between categorical variables)

Why it matters non-directional

Contingency Coefficient is an alternative effect size for chi-square tests. Unlike Cramér's V, C does not reach maximum of 1.0 in all tables - instead, C_max = √((min(r,c)-1)/min(r,c)) varies by table dimensions. Formula: C = √(χ²/(χ²+n)). Cramér's V is generally preferred over C for interpretability.

02Model diagnostics

Assumptions

The core mathematical criteria needed to ensure that statistical testing remains unbiased and valid.

Build your analysis on rock, not sand. Verify the mathematical foundation before building the model.
Integrity Shield
6
Assumptions
3
Critical / High Severity
How to check
Quick
Verify that each variable has distinct categories with no overlap (e.g., education level: HS/Associate/Bachelor/Graduate; religion: Christian/Muslim/Jewish/Hindu/Other). Categories must be exhaustive (all observations classified) and mutually exclusive (each observation in exactly one category)
Rigorous
Check variable types are categorical (factor/character in R, categorical in Python). Ensure no continuous variables without proper categorization. Review contingency table structure - all cells should represent valid combinations of category levels
If violated
If variables are continuous: categorize into meaningful bins (e.g., age into decades, income into quartiles) or use appropriate correlation (Pearson, Spearman, Kendall). If one variable continuous and other categorical: use point-biserial correlation (binary categorical), eta coefficient, or ANOVA (multi-category). Contingency Coefficient requires both variables categorical
pearson correlationspearman correlationkendall tau b
How to check
Quick
Review study design: each observation should represent unique independent unit. Check for repeated measures (same subject multiple times), matched/paired designs, or clustering (students nested within schools, patients within clinics). Examine data for duplicate IDs or temporal dependencies
Rigorous
Verify no duplicate cases. Check for hierarchical/nested structure. If longitudinal data or within-subject repeated measures: standard contingency coefficient inappropriate. Calculate intraclass correlation (ICC) if clustering suspected; ICC > 0.05 indicates dependence. Review data collection protocol for independence violations
If violated
If repeated measures over time: use Cochran's Q test (binary outcomes) or McNemar's test (paired 2×2). If matched pairs: use McNemar's test (2×2) or Stuart-Maxwell test (larger tables). If clustered data: use multilevel/mixed-effects logistic regression with random effects for clusters. If time series: use autocorrelation methods. Never apply standard C to dependent data - inflates Type I error
mcnemarstuart maxwell
How to check
Quick
Compute expected frequencies for each cell: (row total × column total) / grand total. Rule of thumb: ≥80% of cells should have expected frequency ≥5, and NO cell should have expected frequency <1. Check with chi2_result$expected in R or expected_freq() in Python
Rigorous
Calculate all expected frequencies systematically. Count cells violating ≥5 rule. If >20% of cells have expected frequencies <5, chi-square (and thus C) may be unreliable. Identify any cells with expected frequency <1 (serious violation requiring intervention)
If violated
If sparse cells (many expected frequencies <5): (1) Collapse adjacent categories if conceptually meaningful (e.g., merge 'strongly agree'/'agree' into 'agree'); (2) Use Fisher's exact test for 2×2 tables (exact p-value, no C); (3) Use Fisher-Freeman-Halton exact test for larger tables; (4) Increase sample size if possible; (5) Use Monte Carlo simulation for p-value. C can still be reported as descriptive effect size but interpret with caution
How to check
Quick
Calculate C_max = √((min(r,c)-1)/min(r,c)) for your table. For 2×2: C_max = 0.707; for 3×3: C_max = 0.816; for 4×4: C_max = 0.866; for 5×5: C_max = 0.894. C cannot exceed this maximum even for perfect association
Rigorous
Compute C_max explicitly. Compare observed C to C_max to assess relative strength. Consider computing adjusted contingency coefficient C* = C / C_max to rescale to 0-1 range for better interpretability. Recognize that raw C values are not comparable across different table dimensions
If violated
This is inherent limitation of C, not violation per se. Solutions: (1) Report adjusted C* = C / C_max alongside raw C to enable 0-1 interpretation; (2) Prefer Cramér's V over C for standardized reporting (V ranges 0-1 for all tables); (3) If comparing C across studies with different table sizes, standardize using C*; (4) Acknowledge C_max limitation when interpreting: 'C = 0.65 approaches maximum of 0.816 for 3×3 table, indicating strong association'
cramers v
How to check
Quick
Calculate number of cells: rows × columns. Rule of thumb: n should be ≥5× number of cells. For 3×3 table (9 cells), need n ≥45. For 4×5 table (20 cells), need n ≥100. Check average cell count = n/(r×c) is reasonable (≥5-10)
Rigorous
Compute expected frequencies for all cells. If many cells have low expected frequencies, table is sparse and estimates unstable. Use power analysis: for medium effect (C ≈ 0.30), α = .05, power = .80, typical requirement is n ≥ 100-150 depending on table size
If violated
If sample too small for table dimensions: (1) Collapse categories to reduce table size (e.g., 5×5 → 3×3) if conceptually justified; (2) Increase sample size through additional data collection; (3) Use exact tests (Fisher's exact, Fisher-Freeman-Halton) for p-values; (4) Report C as descriptive statistic with caveat about precision (wide confidence intervals). Avoid making strong inferential claims from sparse tables
How to check
Quick
Verify sum of category frequencies equals total sample size (no double-counting or missing). Check categories don't overlap (e.g., age groups 18-25, 26-35, 36-45 are exclusive; 18-25, 20-30 overlap). Ensure all cases classified - check for excessive 'other' or 'missing' category
Rigorous
Cross-tabulate and verify row/column totals sum to n. Check missing data patterns - if >10% missing, handle appropriately (listwise deletion, multiple imputation, or meaningful 'missing' category). Ensure categories are conceptually distinct and exhaustive
If violated
If categories overlap: redefine to be mutually exclusive (e.g., adjust overlapping age ranges). If substantial missing data: use multiple imputation or create separate 'missing/unknown' category only if missingness is informative (e.g., 'refused' for sensitive questions). If categories not exhaustive: add 'other' category to capture all cases. Verify data entry accuracy if totals inconsistent
03Residual Forensics

Diagnostics

Checking residual plots and indices to examine model deviations and ensure standard error integrity.

Trust, but verify. The outliers often hold more truth than the averages.
System Health
Essential checks
  1. Contingency table with row/column totals
  2. Expected frequencies (chi-square assumption check)
  3. Chi-square test statistic and p-value
  4. Contingency Coefficient C with C_max for context
  5. Adjusted C* = C/C_max (rescaled to 0-1)
Recommended checks
  1. Cramér's V for comparison (generally preferred over C)
  2. 95% confidence interval for C or C*
  3. Standardized residuals to identify influential cells
  4. Mosaic plot or heatmap for visualization
  5. Row/column percentages to describe association pattern
  6. Comparison of C with C_max to assess relative strength
  7. Table showing C_max for various table dimensions
  8. Effect size interpretation considering C_max limitation
04Live Instances

Applied Minds

Review concrete study examples, data layout guidelines, and copy executable syntax scripts.

Theory is the map. Practice is the terrain. Simulation bridges the gap.
Applied Wisdom
Example 01

Smoking Status × Lung Disease (3×3 Table with C_max Context)

Research question: Is smoking status associated with lung disease severity? Design: Cross-sectional study of 250 adults (age 40-70) classified by smoking status (never smoker, former smoker, current smoker) and lung disease severity (none/mild, moderate, severe). Both variables ordinal but treated as nominal for C. Hypothesis: Higher smoking exposure associated with greater lung disease severity. Demonstrates C_max interpretation.

DesignCross-sectional observational
# Contingency Coefficient: Smoking × Lung Disease
# 3×3 table demonstrating C_max interpretation

library(tidyverse)
library(vcd)           # For assocstats (includes C)
library(DescTools)     # For ContCoef with CI

set.seed(2025)
n <- 250

# Simulate smoking-lung disease association
smoking_categories <- c("Never", "Former", "Current")
disease_categories <- c("None/Mild", "Moderate", "Severe")

smoking <- sample(smoking_categories, n, replace=TRUE, prob=c(0.40, 0.35, 0.25))

# Lung disease severity depends strongly on smoking
disease <- character(n)
for (i in 1:n) {
  if (smoking[i] == "Never") {
    disease[i] <- sample(disease_categories, 1, prob=c(0.70, 0.25, 0.05))
  } else if (smoking[i] == "Former") {
    disease[i] <- sample(disease_categories, 1, prob=c(0.45, 0.40, 0.15))
  } else {  # Current
    disease[i] <- sample(disease_categories, 1, prob=c(0.20, 0.45, 0.35))
  }
}

data <- data.frame(
  participant_id = 1:n,
  smoking = factor(smoking, levels=smoking_categories),
  disease = factor(disease, levels=disease_categories)
)

head(data, 10)

# === STEP 1: Create Contingency Table ===

cat("=== Contingency Table: Smoking Status × Lung Disease ===\n")
contingency <- table(data$smoking, data$disease)
print(contingency)

cat("\n=== Row Percentages(disease severity within each smoking group) ===\n")
row_pct <- prop.table(contingency, margin=1) * 100
print(round(row_pct, 1))

# === STEP 2: Chi-Square Test ===

chi_result <- chisq.test(contingency)
cat("\n=== Chi-Square Test of Independence ===\n")
print(chi_result)

cat("\nExpected Frequencies:\n")
print(round(chi_result$expected, 2))

min_expected <- min(chi_result$expected)
cat(sprintf("\nMinimum expected frequency: %.2f (should be ≥5)\n", min_expected))

if (min_expected >= 5 & sum(chi_result$expected < 5) / length(chi_result$expected) < 0.20) {
  cat("Chi-square assumptions satisfied ✓\n")
} else {
  cat("WARNING: Chi-square assumptions may be violated\n")
}

cat(sprintf("\nχ²(%d, N=%d) = %.2f, p %s\n",
            chi_result$parameter,
            n,
            chi_result$statistic,
            ifelse(chi_result$p.value < 0.001, "< .001", 
                   sprintf("= %.3f", chi_result$p.value))))

# === STEP 3: Calculate Contingency Coefficient C ===

# Manual calculation
chi2 <- chi_result$statistic
c_raw <- sqrt(chi2 / (chi2 + n))

cat("\n=== Contingency Coefficient Calculation ===\n")
cat(sprintf("C = √(χ²/(χ²+n)) = √(%.2f/(%.2f+%d)) = %.3f\n", 
            chi2, chi2, n, c_raw))

# Calculate C_max
r <- nrow(contingency)
c_cols <- ncol(contingency)
min_dim <- min(r, c_cols)
c_max <- sqrt((min_dim - 1) / min_dim)

cat(sprintf("\nC_max = √((min(r,c)-1)/min(r,c)) = √((%d-1)/%d) = %.3f\n",
            min_dim, min_dim, c_max))
cat(sprintf("\nFor %d×%d table: C can range from 0 to %.3f (not 0 to 1)\n",
            r, c_cols, c_max))

# Adjusted Contingency Coefficient C*
c_adjusted <- c_raw / c_max
cat(sprintf("\nAdjusted C* = C/C_max = %.3f/%.3f = %.3f\n", 
            c_raw, c_max, c_adjusted))
cat("C* rescales C to 0-1 range for interpretability\n")

# Using DescTools (if available)
if (requireNamespace("DescTools", quietly=TRUE)) {
  c_ci <- DescTools::ContCoef(contingency, conf.level=0.95)
  cat(sprintf("\nContingency Coefficient with CI: C = %.3f, 95%% CI [%.3f, %.3f]\n",
              c_ci[1], attr(c_ci, "lwr.ci"), attr(c_ci, "upr.ci")))
}

# === STEP 4: Compare with Cramér's V ===

cat("\n=== Comparison: C vs Cramér's V ===\n")
assoc_stats <- assocstats(contingency)
print(assoc_stats)

v_value <- assoc_stats$cramer
cat(sprintf("\nContingency Coefficient C = %.3f (max = %.3f)\n", c_raw, c_max))
cat(sprintf("Adjusted C* = %.3f\n", c_adjusted))
cat(sprintf("Cramér's V = %.3f (always ranges 0-1)\n", v_value))
cat("\nNote: Cramér's V preferred over C for standardized reporting\n")
cat("V does not have the C_max limitation\n")

# === STEP 5: Effect Size Interpretation ===

cat("\n=== Effect Size Interpretation ===\n")
cat("Interpreting C is complex due to C_max variation by table size\n")
cat("Better to interpret adjusted C* on 0-1 scale:\n\n")

if (c_adjusted < 0.30) {
  c_interp <- "small"
} else if (c_adjusted < 0.50) {
  c_interp <- "medium"
} else {
  c_interp <- "large"
}

cat(sprintf("C* = %.3f → %s effect(using 0.30/0.50 thresholds)\n", 
            c_adjusted, c_interp))
cat(sprintf("Relative to maximum: C is %.0f%% of C_max\n", 
            100 * c_raw / c_max))

# For comparison, interpret Cramér's V (df=2 benchmarks: 0.07/0.21/0.35)
df <- min(r-1, c_cols-1)
cat(sprintf("\nFor comparison, Cramér's V = %.3f\n", v_value))
if (df == 2) {
  if (v_value < 0.21) {
    v_interp <- "small"
  } else if (v_value < 0.35) {
    v_interp <- "medium"
  } else {
    v_interp <- "large"
  }
  cat(sprintf("With df=2, V = %.3f → %s effect\n", v_value, v_interp))
}

# === STEP 6: Standardized Residuals ===

cat("\n=== Standardized Residuals(|z| > 2 significant) ===\n")
std_resid <- chi_result$stdres
print(round(std_resid, 2))

cat("\nCells with |standardized residual| > 2:\n")
for (i in 1:nrow(std_resid)) {
  for (j in 1:ncol(std_resid)) {
    if (abs(std_resid[i,j]) > 2) {
      cat(sprintf("  %s × %s: z = %.2f\n",
                  rownames(contingency)[i],
                  colnames(contingency)[j],
                  std_resid[i,j]))
    }
  }
}

# === STEP 7: Visualizations ===

# Mosaic plot
par(mfrow=c(1,1))
mosaic(contingency, shade=TRUE, legend=TRUE,
       main=sprintf("Smoking × Lung Disease\nC = %.2f (max = %.2f), C* = %.2f",
                    c_raw, c_max, c_adjusted))

# Heatmap
library(pheatmap)
pheatmap(contingency, 
         display_numbers=TRUE, 
         cluster_rows=FALSE, 
         cluster_cols=FALSE,
         main=sprintf("Smoking × Disease(C* = %.2f, %s effect)", 
                      c_adjusted, c_interp),
         color=colorRampPalette(c("white", "orange", "red"))(50))

# Stacked bar plot
data_long <- data %>%
  count(smoking, disease) %>%
  group_by(smoking) %>%
  mutate(pct = n / sum(n) * 100)

ggplot(data_long, aes(x=smoking, y=pct, fill=disease)) +
  geom_bar(stat="identity", color="black") +
  geom_text(aes(label=sprintf("%.0f%%", pct)),
            position=position_stack(vjust=0.5), color="white", size=4) +
  scale_fill_manual(values=c("None/Mild"="#2ECC71", 
                             "Moderate"="#F39C12", 
                             "Severe"="#E74C3C")) +
  labs(title="Lung Disease Severity by Smoking Status",
       subtitle=sprintf("C = %.2f (C* = %.2f after adjustment), V = %.2f",
                        c_raw, c_adjusted, v_value),
       x="Smoking Status", y="Percentage", fill="Disease Severity") +
  theme_classic()

# === STEP 8: Table of C_max Values ===

cat("\n=== Reference: C_max for Different Table Dimensions ===\n")
table_sizes <- data.frame(
  Table = c("2×2", "3×3", "4×4", "5×5", "3×4", "4×5", "2×5"),
  min_dim = c(2, 3, 4, 5, 3, 4, 2),
  C_max = c(sqrt(1/2), sqrt(2/3), sqrt(3/4), sqrt(4/5), 
            sqrt(2/3), sqrt(3/4), sqrt(1/2))
)
table_sizes$C_max <- round(table_sizes$C_max, 3)
print(table_sizes)

cat("\nNote: C_max = √((min(r,c)-1)/min(r,c)) varies by table dimensions\n")
cat("This is why Cramér's V(always 0-1) is preferred over C\n")

# === APA-Style Reporting ===

cat("\n=== APA-Style Report ===\n")
cat(sprintf(
"A chi-square test of independence examined the association between smoking 
status and lung disease severity in %d adults aged 40-70. All expected cell 
frequencies exceeded 5, satisfying chi-square assumptions. There was a 
significant association, χ²(%d, N = %d) = %.2f, p < .001. The Contingency 
Coefficient was C = %.2f, which must be interpreted relative to its maximum 
possible value of C_max = %.2f for a 3×3 table. The adjusted coefficient 
C* = C/C_max = %.2f indicates a %s association on the 0-1 scale. For 
comparison, Cramér's V = %.2f (which always ranges 0-1), also indicating a 
%s effect. Examination of row percentages revealed that current smokers had 
higher rates of severe lung disease(%.0f%%) compared to former smokers 
(%.0f%%) and never smokers(%.0f%%). Standardized residuals identified 
Current Smokers×Severe Disease(z = %.2f) and Never Smokers×None/Mild 
(z = %.2f) as cells contributing most strongly to the association. These 
findings align with epidemiological evidence linking smoking to lung disease 
severity. Note: Cramér's V is generally preferred over the Contingency 
Coefficient for effect size reporting due to its consistent 0-1 range across 
all table dimensions.\n",
n,
chi_result$parameter,
n,
chi_result$statistic,
c_raw,
c_max,
c_adjusted,
c_interp,
v_value,
v_interp,
row_pct["Current", "Severe"],
row_pct["Former", "Severe"],
row_pct["Never", "Severe"],
std_resid["Current", "Severe"],
std_resid["Never", "None/Mild"]
))
Interpretation Blueprint

C = 0.52, C_max = 0.816 for 3×3 table, C* = 0.64 (medium-to-large effect). Current smokers showed 35% severe lung disease vs 5% for never smokers (7× higher rate). Standardized residuals identify Current×Severe (z=5.1) and Never×None/Mild (z=4.8) as strongly positive. C* = 0.64 indicates C is 78% of its maximum, representing substantial association. For comparison, Cramér's V = 0.58 (large effect for df=2), which is more interpretable than C. The C_max limitation (0.816 for 3×3 tables vs 0.707 for 2×2 vs 0.894 for 5×5) makes raw C values non-comparable across studies with different table dimensions, which is why Cramér's V is generally preferred for standardized reporting.

05Tactical Pivots

Alternatives

Structured fallback pathways for choosing alternative tests when normality or slopes requirements fail.

When the path is blocked, pivot. Rigor is not rigidity; it is the intelligent adaptation to reality.
Adaptive Strategy
Measurement Precision Ladder Ideal · Nominal Grid
Ratio / Interval
Consider Pearson r or OLS. Categorical conversion of continuous data destroys the predictive signal.
Information Suicide
Ordinal
Pivot to Kendall's Tau-B or Gamma to preserve the natural order of your categories.
Rank Compression
Nominal
Maintain Contingency Coefficient logic. Ideal for multi-category nominal grids where directionality is absent.
Peak Signal
Temporal Trajectory Audit Static Nominal Snapshot
Static Grid
Single point audit.
Stay with Pearson's C. Neutralize the influence of table size on the chi-square magnitude.
Matched Pairs
Trajectory flips.
Pivot to Stuart-Maxwell or Bowker Symmetry audits to model categorical change over time.
Adaptive Technical Safeguards · adaptive safeguards
non standardized magnitude
  • Cramer's V — Pivot to this elite standard to achieve a magnitude that can reach 1.0 regardless of table size.
  • Tschuprow's T — A more conservative alternative for non-square tables.
sparsity detected
  • Fisher-Freeman-Halton — Calculate exact significance for r x c tables with low cell counts.
  • Monte Carlo χ² — Generate simulated p-values to bypass the expected frequency mandate.
06Adjusted Comparisons

Post-hoc

Group mean comparisons and correction controls (e.g. Tukey HSD, Bonferroni) to protect against Family-Wise Error Rates.

The omnibus test opens the door; post-hoc analysis explores the room.
Forensic Detail
Adjusted Comparisons
  • Compare with Cramér's V (V has better interpretability, reaches 1.0)
  • Examine standardized residuals to identify contributing cells
  • Bootstrap confidence intervals for C
  • Correct C using Sakoda's adjustment for table size
  • Stratified analysis: compute C within subgroups and compare
Interpretation Guidelines

Contingency coefficient C measures association in contingency tables. Traditional post-hoc tests are not applicable.

07Standardized scale impact

Effect Size

Understanding effect sizes (e.g., Cohen's d, Partial Eta-Squared) and clinical impact benchmarks.

Significance is noise. Magnitude is the signal. Measure the impact, not just the probability.
Impact Magnitude

C cannot reach 1.0 except for 2×2 tables. C_max varies by table dimensions: 2×2: 0.707, 3×3: 0.816, 4×4: 0.866, 5×5: 0.894

C* = C/C_max rescales to 0-1 range. Benchmarks for C*: Small < 0.30, Medium 0.30-0.50, Large > 0.50

For same data, C < V always. Cramér's V is preferred over C for standardized reporting

Use C only if: (1) Historical comparison required, (2) Field convention mandates C, (3) Comparing to older literature using C. Always report C_max and C* alongside raw C

Recommended Metric: Cramér's V preferred over Contingency Coefficient C. If reporting C, always include C_max and adjusted C* = C/C_max
Small
0.2
Medium
0.5
Large
0.8
0.50
Cramér's V preferred over Contingency Coefficient C. If reporting C, always include C_max and adjusted C* = C/C_max
Recommended Measure
4
Available Metrics
ReportUse Cramér's V preferred over Contingency Coefficient C. If reporting C, always include C_max and adjusted C* = C/C_max to represent clinical impact magnitude.
08Statistical Power

Sample Size

Guidelines for minimum sample requirements and power analysis parameters.

An underpowered study is an ethical failure. Respect the data by collecting enough of it.
Power Protocol
Floor Requirements

The 'Grid Density' Minimum: A minimum of 40 participants is recommended for a 2x2 table. Larger tables require exponentially more N to ensure the coefficient doesn't collapse to zero due to empty cells.

Effect SizeParametersRequired n
Small Effectw=0.10 (Small)n ≈ 785
Medium Effectw=0.30 (Medium)n ≈ 88
Large Effectw=0.50 (Large)n ≈ 32
Key considerations

The 'Unity Penalty': The Contingency Coefficient (C) can never reach 1.0, even for perfect associations. For a 2x2 table, C_max = 0.707. Interpret the magnitude relative to the table's specific maximum to ensure 'Elite' rigor.

G*Power StrategyBenchmark: χ² tests → Pearson Contingency (C). Parameters: Effect size w, α = .05, Power = .80, df = (r-1)(c-1). Note: The Contingency Coefficient is a 'Shrunk' version of χ², requiring the same N as a standard Chi-Square strike.
09APA narrative blueprint

Reporting

How to compile statistical results into publication prose matching APA and journal style guides.

Data does not speak for itself. It requires a translator. Be clear, be precise, be honest.
Narrative Arc
Worked APA paragraph example
A chi-square test of independence examined the association between smoking status (never, former, current smoker) and lung disease severity (none/mild, moderate, severe) in 250 adults aged 40-70. All expected cell frequencies exceeded 5, satisfying chi-square assumptions. There was a significant association, χ²(4, N = 250) = 68.24, p < .001. The Contingency Coefficient was calculated as C = 0.52, which must be interpreted relative to its maximum possible value of C_max = 0.816 for a 3×3 table. The adjusted coefficient C* = C/C_max = 0.64 indicates a medium-to-large association on the 0-1 scale. For comparison, Cramér's V = 0.58 (which always ranges 0-1), also indicating a large effect for this table dimension. Examination of row percentages revealed that current smokers had substantially higher rates of severe lung disease (35%) compared to former smokers (15%) and never smokers (5%). These findings align with epidemiological evidence linking smoking to lung disease severity. Note: Cramér's V is generally preferred over the Contingency Coefficient for effect size reporting due to its consistent 0-1 range across all table dimensions, eliminating the need for C_max adjustment calculations.
Reusable template

A chi-square test of independence examined the association between Variable 1 and Variable 2 in sample description. Assumption check statement. There was a significant/non-significant association, χ²(df, N = n) = chi-square value, p = or < p-value. The Contingency Coefficient was calculated as C = value, which must be interpreted relative to its maximum possible value of C_max = C_max value for a r×c table. The adjusted coefficient C* = C/C_max = C* value, 95% CI [lower, upper], indicates a small/medium/large association on the 0-1 scale. For comparison: Cramér's V = [V value, which always ranges 0-1.] Describe pattern using row percentages or standardized residuals. Optional: Note that Cramér's V is generally preferred over C for its consistent 0-1 range across all table dimensions.

Essential statistics to report
  • Contingency Coefficient C value
  • C_max for the table dimensions
  • Adjusted C* = C/C_max (rescaled to 0-1)
  • Chi-square statistic, df, and p-value
  • Sample size
  • 95% confidence interval (if available)
  • Statement about C_max limitation
10Exhibit Builder

Manuscript Lab

Copy standard summary tables and forensic reporting grids to outline analysis details.

Table 1: Pearson's Contingency Coefficient for Large Nominal Tables
RelationshipCoefficient (C)Approx pMax possible C
Region ↔ Treatment Choice.32.004.816
Physician Type ↔ Specialty.48< .001.866
Note. Calculated from Chi-Square values. N = 400.
C = .48A strong association given the 3x3 structure. Physician type is a moderate-to-strong predictor of specialty choice.
Header glossary

The Nominal Connector. A Chi-square-based metric that adjusts for sample size but remains influenced by table dimensions.

The Ceiling. Unlike Phi or Cramer's V, C rarely reaches 1.0. It is capped by the number of categories.

11Algorithmic Logic

Command Center

Syntax libraries and function parameters for executing calculations in stats packages.

Code is the modern laboratory. Clean execution ensures reproducible discovery.
Execution Engine
# 1. Execute Contingency Coefficient
DescTools::ContCoeff(table(df$var1, df$var2))

# 2. Corrected C (Sakoda's adjustment)
DescTools::ContCoeff(table(df$x, df$y), correct = TRUE)
Library stack
R
DescTools
Python
scipy
Elite Forensic Strike

Contingency Coefficient is less robust than Cramer's V. Only use it when required for historical comparison with legacy Pearson-C studies.

# Comparison Audit (V vs C)
# Cramer's V is generally preferred for its 0-1 range.
12The Over-adjustment Trap

Common Mistakes

Analytical caveats and corrections to maintain modeling integrity.

Wisdom is learning from the failures of others. Anticipate the error before it occurs.
Defensive Logic
Why it's wrong
C's maximum value depends on table dimensions: C_max = √((min(r,c)-1)/min(r,c)). For 2×2 table, C_max = 0.707; for 3×3, C_max = 0.816; for 5×5, C_max = 0.894. A C of 0.65 might seem large, but if C_max = 0.816, it's only 80% of maximum. Without knowing C_max, C values are uninterpretable.
The correction
ALWAYS report C_max alongside raw C: 'C = 0.52 (C_max = 0.816 for 3×3 table)'. Better: compute adjusted C* = C/C_max to rescale to 0-1: 'C* = 0.64'. Best: use Cramér's V instead, which always ranges 0-1 without adjustment needed.
Why it's wrong
C = 0.40 in 2×2 table (C_max = 0.707) represents 57% of maximum (strong effect). C = 0.40 in 5×5 table (C_max = 0.894) represents 45% of maximum (moderate effect). Comparing 0.40 vs 0.40 ignores that they reflect different relative strengths due to different C_max values.
The correction
When comparing C across studies: (1) Report C_max for each study; (2) Convert to adjusted C* = C/C_max for fair comparison; (3) Better: use Cramér's V which is directly comparable across any table dimensions; (4) In meta-analyses, standardize to common effect size (V or odds ratio) rather than pooling C directly.
Why it's wrong
C is mathematically less convenient than Cramér's V: (1) C requires knowing C_max for interpretation; (2) C needs adjustment (C*) for 0-1 scale; (3) C is less widely used in modern research; (4) V is standard in APA guidelines. Using C without strong reason adds complexity without benefit.
The correction
Default to Cramér's V for categorical associations - it's simpler, more interpretable, and widely recognized. Only use C if: (1) Field convention specifically requires C; (2) Comparing to historical literature using C; (3) Journal/supervisor requests C. If using C, always include C_max, compute C*, and consider reporting V alongside for readers' benefit.
Why it's wrong
Some researchers expect C and V to be equal, causing confusion when C = 0.40 but V = 0.45 for same data. This isn't an error - C is systematically smaller than V due to different formulas. Assuming they should match leads to questioning software/calculations unnecessarily.
The correction
Recognize that C < V always for same data (except 2×2 tables where C and phi are related differently). Formulas differ: C = √(χ²/(χ²+n)) vs V = √(χ²/(n×min(r-1,c-1))). Both are valid effect sizes measuring same association from different mathematical perspectives. Choose one (preferably V) and report consistently.
Why it's wrong
Cohen's benchmarks (small 0.10, medium 0.30, large 0.50) apply to V for df=1, not to raw C. Because C_max < 1.0, applying these benchmarks to C underestimates effect size. A C of 0.30 might be small for V, but if C_max = 0.707, C = 0.30 is 42% of maximum (medium effect).
The correction
To use standard benchmarks with C: (1) First convert to C* = C/C_max; (2) Apply benchmarks to C*: small <0.30, medium 0.30-0.50, large >0.50; (3) Or interpret C relative to C_max: 'C = 0.52 is 64% of C_max = 0.816, indicating substantial association'; (4) Simplest: use Cramér's V and apply df-adjusted benchmarks directly.
Why it's wrong
Reporting 'C = 0.48' without C_max leaves readers unable to judge magnitude. Is 0.48 near maximum (strong) or mid-range (medium)? Without table dimensions or C_max, C values are meaningless. This violates reporting standards and prevents readers from interpreting results.
The correction
When reporting C, always include: (1) Table dimensions (r×c); (2) C_max value with calculation; (3) Adjusted C* = C/C_max; (4) Interpretation relative to C_max. Example: 'C = 0.48, which is 59% of C_max = 0.816 for a 3×3 table (C* = 0.59), indicating a medium association.' Better: report V alongside: 'C = 0.48 (C* = 0.59); Cramér's V = 0.42'.
Why it's wrong
C_max = 1.0 only if min(r,c) is infinite. For finite tables, C_max < 1.0. Assuming C_max = 1.0 leads to incorrect C* calculation and misinterpretation of C values. For example, treating C = 0.70 as 70% of maximum when actual C_max = 0.816 means C is actually 86% of maximum (much stronger than assumed).
The correction
Always calculate C_max explicitly: C_max = √((min(r,c)-1)/min(r,c)). For 2×2: 0.707; 3×3: 0.816; 4×4: 0.866; 5×5: 0.894; etc. Use this to compute C* = C/C_max. Never assume C_max = 1.0 for any finite table. If unsure, use Cramér's V which always ranges 0-1 by design.
Why it's wrong
If researchers use C without acknowledging V is standard, readers/reviewers may question methodology. C is older measure; V was developed specifically to address C's limitation (varying C_max). Using C without justification suggests unfamiliarity with current standards or ignoring statistical developments.
The correction
If using C, explicitly state reason: 'Contingency Coefficient C was used to enable comparison with [historical study] which reported C' or 'Field convention in [discipline] uses C'. Acknowledge V's advantages: 'While Cramér's V is generally preferred for its 0-1 range, we report C for [specific reason].' If no strong reason exists, default to V in all new research.
13Academic Lineage

References

Scholarly lineage and citation keys grounding the statistical framework.

We stand on the shoulders of giants. Honor the source of the method.
Academic Lineage
[1]
Pearson, K. (1904). On the theory of contingency and its relation to association and normal correlation. Drapers' Company Research Memoirs Biometric Series I.
Original development of Contingency Coefficient C as measure of association in contingency tables. Historical foundation.
[2]
Cramér, H. (1946). Mathematical Methods of Statistics. Princeton University Press.
Introduced Cramér's V to address C's limitation of not reaching 1.0. V became preferred measure for chi-square effect size due to consistent 0-1 range.
[3]
Yule, G. U., & Kendall, M. G. (1950). An Introduction to the Theory of Statistics (14th ed.). Charles Griffin & Company.
Classic textbook discussing relationship between C, phi, and other categorical association measures. Explains C_max calculation.
[4]
Goodman, L. A., & Kruskal, W. H. (1954). Measures of association for cross classifications. Journal of the American Statistical Association, 49(268), 732-764.
Comprehensive review of categorical association measures including C, V, and PRE measures. Establishes preference for measures with clear 0-1 range.
doi: 10.2307/2281536
[5]
Sheskin, D. J. (2011). Handbook of Parametric and Nonparametric Statistical Procedures (5th ed.). Chapman & Hall/CRC.
Detailed coverage of Contingency Coefficient with C_max adjustment formulas and comparison to Cramér's V. Recommends V for routine use.
[6]
American Psychological Association. (2020). Publication Manual of the American Psychological Association (7th ed.).
APA style guide recommends Cramér's V over Contingency Coefficient C for reporting categorical associations. Emphasizes effect size reporting standards.
statminds · ContingencyMind reference · v2.2 · updated 2026-01-1715 of 15 sections