Goodman-Kruskal Gamma (γ)
Symmetric ordinal association measure based on concordant and discordant pairs; ignores all ties, ranges from -1 to +1..
What is it?
Goodman-Kruskal Gamma measures ordinal or nominal association strength, evaluating concordances or error reduction when predicting categories.
When to use it
- Gamma / Somers' D: Ordinal scales where ties exist (ignores ties in Gamma, penalizes in Somers).
- Lambda: Nominal tables measuring predictive error reduction (proportional reduction in error).
Core Idea
These ordinal tests check if ranks match or if categorical labels can predict outcome groupings:
Hypotheses
How it works
- Construct cross-tabulated ordinal categories.
- Evaluate concordant pair paths vs. discordant paths.
- Compute the specific ratio index (e.g. Gamma = (C-D)/(C+D)).
- Compute significance approximation.
Assumptions
Important Note
💡 Ties Sensitivity: Gamma ignores ties, which can overestimate association strength in tables with high ties. Somers' D adjusts for ties on the dependent variable.
Quick Example
| Likert Scale | Agree | Neutral | Disagree |
|---|---|---|---|
| Male | 24 | 15 | 12 |
| Female | 18 | 20 | 10 |
Goodman-Kruskal Gamma Laboratory
Manipulate association strength to see how sample dots shift between cell categories.
| Metric | Value |
|---|---|
| Concordant Pairs (C) | 1789 |
| Discordant Pairs (D) | 88 |
| Calculated Score | 0.9062 |
| Significance approx. p | 0.0003 |
Hypotheses
Pragmatic null and alternative hypotheses defined in mathematical notation.
H₀: γ = 0 (no monotonic association between variables)
Hₐ: γ ≠ 0 (monotonic association exists)
Tests symmetric monotonic association based purely on concordant vs discordant pairs. Unlike Kendall's tau-b (adjusts for all ties) or Somers' D (adjusts asymmetrically), gamma completely ignores tied pairs. Can be one-tailed if direction predicted a priori. Gamma typically larger than tau-b for same data due to tie exclusion.
Assumptions
The core mathematical criteria needed to ensure that statistical testing remains unbiased and valid.
Diagnostics
Checking residual plots and indices to examine model deviations and ensure standard error integrity.
- Cross-tabulation (contingency table) to visualize association pattern
- Check for monotonic diagonal or anti-diagonal pattern
- Examine 95% confidence interval for gamma
- Calculate proportion of concordant vs discordant pairs
- Verify sample size and cell counts are adequate
- Heatmap or mosaic plot of contingency table
- Compare gamma with Kendall's tau-b to assess tie influence
- Calculate percentage of tied pairs to understand why gamma differs from tau-b
- Stacked bar chart showing conditional distributions
- Sensitivity analysis: robustness to category collapsing
Applied Minds
Review concrete study examples, data layout guidelines, and copy executable syntax scripts.
Political Ideology × Policy Support (Symmetric Ordinal Association)
Research question: Is political ideology (liberal to conservative) associated with support for environmental policy? Design: Survey of 180 voters rating ideology (5-point: very liberal to very conservative) and policy support (5-point: strongly oppose to strongly support). Both ordinal, symmetric relationship (no clear DV/IV). Hypothesis: More liberal ideology associated with greater policy support.
# Goodman-Kruskal Gamma: Political Ideology × Policy Support
# Symmetric ordinal association (no clear DV/IV)
library(tidyverse)
library(DescTools) # For GoodmanKruskalGamma
library(vcd) # For mosaic plots
library(MASS) # For ordinal regression
set.seed(2025)
n <- 180
# Political ideology (1-5: very liberal to very conservative)
ideology <- sample(1:5, n, replace = TRUE,
prob = c(0.20, 0.25, 0.30, 0.15, 0.10))
# Policy support (1-5) strongly associated with ideology
# More liberal (low ideology) → more support (high policy)
latent_support <- 6 - 0.9 * ideology + rnorm(n, 0, 0.8)
policy_support <- cut(latent_support,
breaks = c(-Inf, 1.5, 2.5, 3.5, 4.5, Inf),
labels = 1:5)
policy_numeric <- as.numeric(policy_support)
data <- data.frame(
respondent_id = 1:n,
ideology = factor(ideology, levels = 1:5,
labels = c("Very Liberal", "Liberal", "Moderate",
"Conservative", "Very Conservative")),
ideology_num = ideology,
policy_support = factor(policy_numeric, levels = 1:5,
labels = c("Strongly Oppose", "Oppose", "Neutral",
"Support", "Strongly Support")),
policy_num = policy_numeric
)
head(data, 10)
# === STEP 1: Descriptive Statistics ===
cat("=== FREQUENCY DISTRIBUTIONS ===\n")
cat("\nPolitical Ideology:\n")
table(data$ideology)
cat("\nEnvironmental Policy Support:\n")
table(data$policy_support)
# === STEP 2: Cross-Tabulation ===
cat("\n=== CONTINGENCY TABLE ===\n")
contab <- table(data$ideology, data$policy_support)
print(contab)
cat("\n=== ROW PERCENTAGES(% within each ideology level) ===\n")
print(round(prop.table(contab, margin = 1) * 100, 1))
# Heatmap
library(pheatmap)
pheatmap(contab,
cluster_rows = FALSE,
cluster_cols = FALSE,
display_numbers = TRUE,
main = "Ideology × Policy Support(Frequencies)",
xlab = "Policy Support",
ylab = "Political Ideology")
# Mosaic plot
mosaic(~ ideology + policy_support, data = data,
shade = TRUE, legend = TRUE,
main = "Mosaic: Political Ideology × Policy Support")
# === STEP 3: Compute Goodman-Kruskal Gamma ===
cat("\n=== GOODMAN-KRUSKAL GAMMA ===\n")
# Gamma (ignores all tied pairs)
gamma_result <- GoodmanKruskalGamma(data$ideology_num, data$policy_num,
conf.level = 0.95)
cat(sprintf("Gamma(γ) = %.3f\n", gamma_result[1]))
cat(sprintf("95%% CI: [%.3f, %.3f]\n", gamma_result[2], gamma_result[3]))
# === STEP 4: Concordant and Discordant Pairs ===
n_pairs <- n * (n - 1) / 2
# Calculate manually
concordant <- sum(outer(data$ideology_num, data$ideology_num, "<") &
outer(data$policy_num, data$policy_num, "<")) +
sum(outer(data$ideology_num, data$ideology_num, ">") &
outer(data$policy_num, data$policy_num, ">"))
discordant <- sum(outer(data$ideology_num, data$ideology_num, "<") &
outer(data$policy_num, data$policy_num, ">")) +
sum(outer(data$ideology_num, data$ideology_num, ">") &
outer(data$policy_num, data$policy_num, "<"))
cat(sprintf("\nTotal pairs: %.0f\n", n_pairs))
cat(sprintf("Concordant pairs: %d(%.1f%%)\n",
concordant, 100 * concordant / n_pairs))
cat(sprintf("Discordant pairs: %d(%.1f%%)\n",
discordant, 100 * discordant / n_pairs))
cat(sprintf("Tied pairs: %d(%.1f%%)\n",
n_pairs - concordant - discordant,
100 * (n_pairs - concordant - discordant) / n_pairs))
cat("\nNote: Gamma = (C - D) / (C + D), ignoring tied pairs\n")
cat(sprintf("Manual calculation: (%.0f - %.0f) / (%.0f + %.0f) = %.3f\n",
concordant, discordant, concordant, discordant,
(concordant - discordant) / (concordant + discordant)))
# === STEP 5: Compare with Kendall's Tau-b ===
cat("\n=== COMPARISON WITH KENDALL'S TAU-B ===\n")
tau_b <- cor(data$ideology_num, data$policy_num, method = "kendall")
cat(sprintf("Kendall's tau-b = %.3f\n", tau_b))
cat(sprintf("Gamma = %.3f\n", gamma_result[1]))
cat(sprintf("Ratio γ/τb = %.2f\n", gamma_result[1] / tau_b))
cat("\nWhy gamma > tau-b:\n")
cat(" Gamma ignores tied pairs(focuses on concordant vs discordant)\n")
cat(" Tau-b adjusts for ties, diluting the association\n")
cat(" Gamma typically 1.2-1.5× larger than tau-b for same data\n")
# === STEP 6: Statistical Significance Testing ===
cat("\n=== HYPOTHESIS TEST ===\n")
# Asymptotic test using CI
ci_width <- gamma_result[3] - gamma_result[2]
se_approx <- ci_width / (2 * 1.96)
z_stat <- gamma_result[1] / se_approx
p_value <- 2 * pnorm(-abs(z_stat))
cat(sprintf("z-statistic = %.2f\n", z_stat))
cat(sprintf("p-value = %.4f\n", p_value))
if (p_value < 0.001) {
cat("Result: Highly significant(p < .001)\n")
} else if (p_value < 0.05) {
cat("Result: Significant(p < .05)\n")
} else {
cat("Result: Not significant(p ≥ .05)\n")
}
# === STEP 7: Effect Size Interpretation ===
cat("\n=== EFFECT SIZE INTERPRETATION ===\n")
cat("Gamma magnitude guidelines:\n")
cat(" |γ| < 0.1: negligible\n")
cat(" 0.1 ≤ |γ| < 0.3: small\n")
cat(" 0.3 ≤ |γ| < 0.6: moderate\n")
cat(" |γ| ≥ 0.6: large\n\n")
gamma_val <- abs(gamma_result[1])
if (gamma_val < 0.1) {
strength <- "negligible"
} else if (gamma_val < 0.3) {
strength <- "small"
} else if (gamma_val < 0.6) {
strength <- "moderate"
} else {
strength <- "large"
}
cat(sprintf("Observed γ = %.3f: %s effect\n", gamma_result[1], strength))
# PRE interpretation for gamma
cat("\nPRE interpretation(for concordant vs discordant pairs only):\n")
cat(sprintf("Of pairs that are not tied, %.0f%% more are concordant than discordant\n",
abs(gamma_result[1]) * 100))
# === STEP 8: Visualization ===
cat("\n=== VISUALIZATIONS ===\n")
# Stacked bar chart
ggplot(data, aes(x = ideology, fill = policy_support)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent) +
scale_fill_brewer(palette = "RdYlGn", direction = -1) +
labs(title = "Policy Support by Political Ideology",
subtitle = sprintf("Gamma = %.2f (%s negative association)",
gamma_result[1], strength),
x = "Political Ideology",
y = "Proportion",
fill = "Policy Support") +
theme_classic() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
# Mean policy support by ideology
mean_support <- data %>%
group_by(ideology_num) %>%
summarise(mean_policy = mean(policy_num),
se = sd(policy_num) / sqrt(n()))
ggplot(mean_support, aes(x = ideology_num, y = mean_policy)) +
geom_line(linewidth = 1.2, color = "blue") +
geom_point(size = 3, color = "blue") +
geom_errorbar(aes(ymin = mean_policy - 1.96*se,
ymax = mean_policy + 1.96*se),
width = 0.2) +
labs(title = "Mean Policy Support by Ideology",
subtitle = "Clear negative monotonic trend",
x = "Political Ideology(1=Very Liberal to 5=Very Conservative)",
y = "Mean Policy Support(±95% CI)") +
theme_classic()
# === APA-STYLE REPORTING ===
cat("\n=== APA-STYLE REPORT ===\n")
cat(sprintf(
"Goodman-Kruskal gamma was computed to assess the symmetric ordinal association
between political ideology(5 ordered categories from very liberal to very
conservative) and environmental policy support(5 ordered categories from strongly
oppose to strongly support) in 180 voters. Gamma was chosen over Kendall's tau-b
because it focuses on the pure concordant vs discordant relationship, ignoring
tied pairs, making it useful for comparing associations across studies with varying
tie structures.
A large negative association was found, γ = %.2f, 95%% CI [%.2f, %.2f], z = %.2f,
p < .001, indicating that more liberal ideology was strongly associated with greater
environmental policy support(negative because liberal=1 and high support=5). The
effect size was %s according to standard interpretation guidelines. Of observation
pairs that were not tied, %.0f%% more were concordant(both variables moved in same
direction) than discordant.
The analysis revealed %.0f%% concordant pairs, %.0f%% discordant pairs, and %.0f%%
tied pairs(on at least one variable). Gamma(%.2f) was larger than Kendall's tau-b
(%.2f) by a factor of %.2f, reflecting gamma's exclusion of ties. These findings
align with political science research showing strong associations between liberal
ideology and environmental support(Dunlap et al., 2016).\n",
gamma_result[1], gamma_result[2], gamma_result[3], z_stat, strength,
abs(gamma_result[1]) * 100,
100 * concordant / n_pairs,
100 * discordant / n_pairs,
100 * (n_pairs - concordant - discordant) / n_pairs,
gamma_result[1], tau_b, abs(gamma_result[1] / tau_b)
))γ = -0.68, 95% CI [-0.76, -0.60], p < .001 (large effect). Strong negative association: liberal ideology associated with high policy support (negative because liberal coded low, support coded high). Of non-tied pairs, 68% more concordant than discordant. Gamma (-0.68) > tau-b (-0.52) by 1.31× due to tie exclusion. Results consistent with political ideology-environment literature (Dunlap et al., 2016).
Alternatives
Structured fallback pathways for choosing alternative tests when normality or slopes requirements fail.
- Kendall's Tau-B — Penalize the association for the presence of identical ranks.
- Somers' D — Utilize the asymmetric audit to find the directional influence.
- Cramer's V — The only valid path if the categories are unordered names (e.g., Hospital A vs B).
- Chi-Square Independence — If the relationship is cyclic or 'U-shaped', the Gamma strike will miss the signal.
Post-hoc
Group mean comparisons and correction controls (e.g. Tukey HSD, Bonferroni) to protect against Family-Wise Error Rates.
Post-hoc pairwise tests defined for this model.
Gamma is an audit of 'Agreement Probability'. Use pair partitioning to find the specific thresholds where the rank-order connection is most authoritative.
Effect Size
Understanding effect sizes (e.g., Cohen's d, Partial Eta-Squared) and clinical impact benchmarks.
|γ| < 0.1: negligible; 0.1-0.3: small; 0.3-0.6: moderate; ≥0.6: large
For non-tied pairs: |γ| = proportion excess of concordant over discordant pairs. γ = 0.60 means 60% more concordant than discordant among non-tied pairs
Gamma typically 1.2-1.5× larger than tau-b for same data because gamma excludes ties while tau-b adjusts for them. Use gamma to compare across studies with varying tie structures
0.2
0.5
0.8
Sample Size
Guidelines for minimum sample requirements and power analysis parameters.
The 'Ordinal Parity' Minimum: A minimum of 50 participants is required. Gamma audits the 'Order Agreement'—it becomes unstable and unreliable if the number of 'Discordant Pairs' is too small.
| Effect Size | Parameters | Required n |
|---|---|---|
| Small Effect | G = .10 (Small) | n ≈ 600 total |
| Medium Effect | G = .30 (Medium) | n ≈ 110 total |
| Large Effect | G = .50 (Large) | n ≈ 45 total |
The 'Tie Bias': Gamma ignores ties entirely. If 80% of your data are tied (e.g., everyone scores 'Medium'), Gamma will claim 'Perfect Agreement' based on a tiny subset of the data. Audit the 'Tie Percentage' before trusting the result.
Reporting
How to compile statistical results into publication prose matching APA and journal style guides.
Goodman-Kruskal gamma was computed to assess the symmetric ordinal association between Variable 1 (k ordered categories) and Variable 2 (j ordered categories) in sample description. Gamma was chosen over tau-b / because it ignores tied pairs / for comparability across studies. Assumptions checked. There was a significant/non-significant positive/negative association, γ = value, 95% CI [lower, upper], z = z-value, p = or < p-value, indicating substantive interpretation. The effect size was small/moderate/large. Of observation pairs that were not tied, |γ|×100% more were concordant than discordant. Optional: comparison with tau-b. These findings connection to theory/research.
- Gamma (γ) value
- 95% confidence interval
- z-statistic
- p-value
- Sample size
- Proportion concordant and discordant pairs
- Comparison with tau-b if reported
Manuscript Lab
Copy standard summary tables and forensic reporting grids to outline analysis details.
| Variable Pair | Gamma (γ) | ASE | p-value |
|---|---|---|---|
| Stress Rank ↔ Error Rank | .65 | .082 | < .001 |
| Training Rank ↔ Skill Rank | .42 | .095 | .002 |
The Concordance Probability. Represents the probability that a random pair will have the same rank order across both variables, ignoring ties.
The core assumption that increase in one variable corresponds to increase (or decrease) in the other.
Command Center
Syntax libraries and function parameters for executing calculations in stats packages.
# 1. Execute Gamma
DescTools::GoodmanKruskalGamma(df$var1, df$var2)
# 2. Detailed Ordinal Table
vcd::assocstats(table(df$x, df$y))Gamma overestimates association when there are many ties. If your data has frequent ties, prioritize Kendall's Tau-b or Somers' D.
# Multi-index Ordinal Audit
# Compare Gamma, Tau-b, and Tau-c simultaneously.Common Mistakes
Analytical caveats and corrections to maintain modeling integrity.
References
Scholarly lineage and citation keys grounding the statistical framework.