library(rstatix)
tulip <- c(red = 81, yellow = 50, white = 27)
tulip red yellow white
81 50 27
Test whether one categorical variable’s proportions match a theoretical distribution — equal or unequal expected proportions, with pairwise post-hoc
Learn to run the chi-square goodness-of-fit test in R — compare the observed proportions of one categorical variable to expected (theoretical) proportions, equal or unequal. Use rstatix chisq_test() with a p argument, follow up with pairwise post-hoc comparisons, and use the exact multinomial test for small samples.
June 23, 2026
July 7, 2026
rstatix::chisq_test() (or base chisq.test()): for equal expected proportions pass just the counts; for unequal expected proportions add p = c(...).pairwise_chisq_gof_test()) to see which categories differ.multinom_test()).The chi-square goodness-of-fit test works on a single categorical variable: it asks whether its observed category proportions match a set of expected proportions. Unlike the test of independence (which needs two variables and a two-way table), goodness-of-fit compares one variable’s distribution to a theoretical one.
The classic scenario: researchers collected wild tulips — 81 red, 50 yellow, 27 white — and ask whether the colours are equally distributed, or whether they fit an expected ratio. This lesson runs both cases with rstatix.
Goodness-of-fit hypotheses. H₀: the observed proportions equal the expected proportions (the data fit the distribution). Hₐ: they differ. A significant result rejects the expected distribution.
Are the three colours equally frequent? If so, each expected proportion is 1/3. Pass just the counts — chisq_test() defaults to equal proportions:
# A tibble: 1 × 6
n statistic p df method p.signif
* <int> <dbl> <dbl> <dbl> <chr> <chr>
1 3 27.9 0.00000088 2 Chi-square test ****
The colours are not equally distributed, χ²(2) = 27.9, p < 0.0001 — red is far more common than white. The same test in base R gives the identical statistic and p-value:
Do the colours fit a known 3 : 2 : 1 ratio (red : yellow : white)? That ratio gives expected proportions of 1/2, 1/3, 1/6. Pass them with p:
# A tibble: 1 × 6
n statistic p df method p.signif
* <int> <dbl> <dbl> <dbl> <chr> <chr>
1 3 0.203 0.904 2 Chi-square test ns
Here χ²(2) = 0.20, p = 0.90 — not significant, so the observed counts fit the 3 : 2 : 1 ratio well. (The order of p must match the order of the categories.)
When the equal-proportions test is significant, pairwise comparisons show which colours differ:
# A tibble: 3 × 8
n group1 group2 statistic p df p.adj p.adj.signif
* <int> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
1 2 red yellow 7.34 0.00676 1 0.0135 *
2 2 red white 27 0.000000203 1 0.000000609 ****
3 2 yellow white 6.87 0.00876 1 0.0135 *
All three colours differ significantly from each other (p.adj < 0.05) — red vs white most strongly.
The chi-square approximation needs expected counts ≥ 5. For small samples, the exact multinomial test makes no approximation:
# A tibble: 1 × 2
p p.signif
* <dbl> <chr>
1 0.000000711 ****
(With these large counts it agrees with chi-square; the exact test matters when counts are small.)
library(rstatix)
library(ggpubr)
tulip <- c(red = 81, yellow = 50, white = 27)
df <- data.frame(color = names(tulip), count = as.numeric(tulip))
stat.test <- chisq_test(tulip)
ggbarplot(df, x = "color", y = "count", fill = "color", palette = "jco",
label = TRUE, ylab = "Count", xlab = "Tulip colour") +
labs(subtitle = get_test_label(stat.test, detailed = TRUE))
A chi-square goodness-of-fit test showed that the tulip colours were not equally distributed, χ²(2) = 27.9, p < 0.001; pairwise comparisons found all three colours differed. However, the counts were consistent with the expected 3 : 2 : 1 ratio, χ²(2) = 0.20, p = 0.90.
Goodness-of-fit uses the same statistic as the independence test, \(\chi^2 = \sum_i \dfrac{(O_i - E_i)^2}{E_i}\), but the expected count for each category is \(E_i = N \times p_i\) (total × the hypothesized proportion), and the degrees of freedom are \(k - 1\) for \(k\) categories (one fewer than the number of categories, since the counts sum to \(N\)).
Test a die for fairness — are the six faces equally likely? Edit the counts and re-run; the sandbox boots on first Run.
Ask Prova “I have counts in categories and expected proportions — run a chi-square goodness-of-fit test and tell me whether my data fits” — it answers with rstatix code you can run on your own counts. The runtime is the judge. Ask Prova →
You mixed up the order of p. The expected proportions in p = c(...) must be in the same order as the counts/categories — a mismatch tests the wrong hypothesis.
Expected counts are below 5. The chi-square approximation is unreliable — use the exact multinomial test (multinom_test()).
You have two variables, not one. Goodness-of-fit is for one categorical variable vs expected proportions. To test whether two variables are associated, use the chi-square test of independence.
It tests whether the observed proportions of a single categorical variable match a set of expected (theoretical) proportions — for example, whether tulip colours are equally frequent, or fit a known ratio. A significant result means the data do not fit the expected distribution.
Goodness-of-fit uses one categorical variable and compares it to expected proportions. Independence uses two categorical variables and tests whether they are associated (from a two-way table). Same statistic, different setup.
Pass them to the p argument as a vector that sums to 1, in the same order as the categories — e.g. chisq_test(counts, p = c(1/2, 1/3, 1/6)) for a 3 : 2 : 1 ratio. With no p, the test assumes equal proportions.
Fill the blank with chisq_test (no p = equal proportions). For question 2, recall the pairwise follow-up.
For question 2: run pairwise comparisons (pairwise_chisq_gof_test()) to see which categories differ, or inspect the standardized residuals to see which are over- (positive) or under-represented (negative).
multinom_test()).You can now run the chi-square goodness-of-fit test in R: pass the counts to chisq_test() for equal expected proportions, add p = c(...) for unequal ones, follow a significant result with pairwise_chisq_gof_test(), and switch to the exact multinomial test for small samples. It is the test for checking whether one categorical variable fits a theoretical distribution.
Prove you can do it. Master the whole Categorical Analysis in R series — track your path, build projects, and earn a certificate.
Go Pro — unlimited Prova on your own data and a verifiable certificate that proves the skill.
from $15/mo billed yearly
✓ You're Pro — keep going. The runtime is the judge.
Get new R & Python lessons by email
Practical, reproducible, no spam. Unsubscribe anytime.
Double opt-in. We never share your email.
Every result on this page was produced by the code shown, run at build time against a pinned R environment — edit any block and Run to reproduce it yourself.
@online{2026,
author = {},
title = {Chi-Square {Goodness-of-Fit} {Test} in {R:} {Observed} Vs
{Expected} {Proportions}},
date = {2026-06-23},
url = {https://www.datanovia.com/learn/biostatistics/categorical/chi-square-goodness-of-fit-test-in-r},
langid = {en}
}