Cochran-Armitage Trend Test in R: Test a Trend in Proportions

Test whether a binomial proportion increases or decreases across an ordered exposure — the chi-square test for trend, more powerful than a plain chi-square

Biostatistics

Learn to run the Cochran-Armitage trend test in R — test whether a yes/no proportion changes linearly across the ordered levels of an exposure (dose, age group, severity). Run it with rstatix prop_trend_test() on a 2×k contingency table, and see why it is more powerful than a plain chi-square when the categories are ordered.

Published

June 23, 2026

Modified

July 7, 2026

TipKey takeaways
  • The Cochran-Armitage trend test (chi-square test for trend) tests whether a binomial proportion increases or decreases linearly across the ordered levels of an exposure — dose, age group, severity, etc.
  • Run it with rstatix::prop_trend_test() on a 2 × k contingency table (two outcome rows, k ordered columns).
  • It is more powerful than a plain chi-square test when the columns are ordered, because it tests specifically for a trend rather than any difference.
  • A significant result means the proportion changes monotonically with the ordered exposure.

Introduction

When one categorical variable is ordered — dose levels, age bands, disease stages — and the other is a yes/no outcome, you often care about a specific question: does the proportion of “yes” rise or fall as the exposure increases? A plain chi-square test only asks whether the proportions differ at all, ignoring the order. The Cochran-Armitage trend test uses the ordering, testing for a linear trend in the proportions — and is more powerful for it.

The scenario here: does the proportion of people with renal stones increase across age groups? This lesson runs it with rstatix on the renalstone data.

Note

Cochran-Armitage hypotheses. H₀: there is no linear trend in the proportion across the ordered levels. Hₐ: the proportion changes monotonically (increases or decreases) with the ordered exposure.

The data: renal stones by age group

We use the renalstone dataset from datarium and cross-tabulate stone status × age group (three ordered bands) with base R:

library(rstatix)

data("renalstone", package = "datarium")
xtab <- xtabs(~ stone + age, data = renalstone)
xtab
     age
stone 30-39 40-49 50-59
  yes   384   536   335
  no    951   869   438

The proportion with a stone clearly rises across the age bands:

library(rstatix)

data("renalstone", package = "datarium")
xtab <- xtabs(~ stone + age, data = renalstone)

round(prop.table(xtab, margin = 2)["yes", ], 3)   # stone rate per age group
30-39 40-49 50-59 
0.288 0.381 0.433 

≈ 29% → 38% → 43% — a steady increase with age.

Run the trend test

prop_trend_test() takes the 2 × k table and assigns scores (1, 2, 3, …) to the ordered columns by default:

library(rstatix)

data("renalstone", package = "datarium")
xtab <- xtabs(~ stone + age, data = renalstone)

prop_trend_test(xtab)
# A tibble: 1 × 6
      n statistic        p p.signif    df method               
* <int>     <dbl>    <dbl> <chr>    <dbl> <chr>                
1  3513      49.7 1.78e-12 ****         1 Chi-square trend test

There is a significant increasing trend in the renal-stone proportion across age groups, χ²(1) = 49.7, p < 0.0001 — the risk rises with age. (Note 1 degree of freedom: the trend test uses the ordering to focus all its power on the linear component, unlike a plain chi-square which would have k − 1 df.)

Tip

Custom scores. By default the levels score 1, 2, 3, …. If the ordered variable has meaningful numeric values (e.g. doses 0, 10, 50 mg), pass them with score = c(0, 10, 50) so the trend reflects the real spacing.

Plot it

library(rstatix)
library(ggpubr)

data("renalstone", package = "datarium")
xtab <- xtabs(~ stone + age, data = renalstone)
prop.df <- data.frame(
  age = colnames(xtab),
  prop = as.numeric(prop.table(xtab, margin = 2)["yes", ])
)
stat.test <- prop_trend_test(xtab)

ggbarplot(prop.df, x = "age", y = "prop", fill = "#3a86d4",
          ylab = "Proportion with stone", xlab = "Age group") +
  labs(subtitle = get_test_label(stat.test, detailed = TRUE))

A bar chart of the proportion with renal stones across three ordered age groups, rising from about 0.29 to 0.43, with the trend-test p-value in the subtitle.

Report

A Cochran-Armitage test for trend showed that the proportion of individuals with renal stones increased significantly across the ordered age groups, χ²(1) = 49.7, p < 0.001 (29%, 38%, 43%).

The test assigns a score \(x_j\) to each ordered level \(j\) and tests whether the proportions \(p_j\) follow a line in those scores. The statistic is essentially a \(\chi^2\) on 1 degree of freedom based on the slope of proportion against score — equivalently \(z^2\) from a weighted linear regression of \(p_j\) on \(x_j\). Concentrating the test on the linear (trend) component is why it is more powerful than the general \((k-1)\)-df chi-square when a monotonic trend is the real alternative.

Try it live

Test for a dose-response trend on your own ordered table. Edit the counts and re-run; the sandbox boots on first Run.

🟢 With an AI agent

Ask Prova “I have a yes/no outcome across ordered dose levels — test whether the proportion shows a trend with the Cochran-Armitage test” — it answers with rstatix code you can run on your own table. The runtime is the judge. Ask Prova →

Common issues

Your exposure isn’t ordered. The trend test only makes sense when the columns have a meaningful order (dose, age, stage). For unordered categories use a plain chi-square test.

You ignored the real spacing. Default scores are 1, 2, 3, … (equal spacing). If your levels are doses like 0, 10, 50, pass score = c(0, 10, 50) so the trend reflects the actual distances.

The proportions go up then down. The Cochran-Armitage test looks for a monotonic linear trend; a U-shaped pattern can give a non-significant result even though the groups clearly differ — inspect the plot, and consider a plain chi-square for any difference.

Frequently asked questions

It tests whether a binomial (yes/no) proportion changes linearly across the ordered levels of an exposure — for example, whether a disease rate rises with dose or age. Also called the chi-square test for trend, it uses the ordering of the categories, making it more powerful than a plain chi-square for detecting a monotonic trend.

The plain chi-square test of independence tests whether the proportions differ at all (ignoring order), on k − 1 degrees of freedom. The Cochran-Armitage test uses the order of the columns to test specifically for a linear trend, on 1 degree of freedom — so it has more power when a trend is the real pattern.

prop_trend_test() scores the levels 1, 2, 3, … by default (equal spacing). If the ordered variable has real numeric values (e.g. doses), pass them via score = c(...) so the trend reflects the actual spacing between levels.

Test your understanding

  1. Run it. In the live cell, test for a dose-response trend in the table. Fill the blank. Is there a significant trend?
  2. Conceptual. Why does the trend test have only 1 degree of freedom while a plain chi-square on the same table has more?

Fill the blank with prop_trend_test. For question 2, recall that the trend test focuses on a single direction (the linear component).

xt <- as.table(rbind(event = c(5, 12, 20, 28), none = c(45, 38, 30, 22)))
prop_trend_test(xt)   #> significant increasing trend.

For question 2: the Cochran-Armitage test concentrates all its power on the linear trend — a single parameter (the slope of proportion against the ordered score) — so it uses 1 degree of freedom. A plain chi-square allows the proportions to differ in any pattern, costing k − 1 degrees of freedom and diluting its power against a monotonic alternative.

TipWhich test when?

Conclusion

You can now run the Cochran-Armitage trend test in R: cross-tabulate the 2 × k table and run prop_trend_test() to test for a linear trend in a proportion across ordered categories — more powerful than a plain chi-square because it uses the ordering. Set custom scores when the levels have meaningful spacing, and reach for it whenever you expect a dose-, age- or severity-response.

Reuse

Citation

BibTeX citation:
@online{2026,
  author = {},
  title = {Cochran-Armitage {Trend} {Test} in {R:} {Test} a {Trend} in
    {Proportions}},
  date = {2026-06-23},
  url = {https://www.datanovia.com/learn/biostatistics/categorical/cochran-armitage-trend-test-in-r},
  langid = {en}
}
For attribution, please cite this work as:
“Cochran-Armitage Trend Test in R: Test a Trend in Proportions.” 2026. June 23. https://www.datanovia.com/learn/biostatistics/categorical/cochran-armitage-trend-test-in-r.