PAGE_TREND_TEST

Overview

The PAGE_TREND_TEST function performs Page’s L test (also known as Page’s trend test), a nonparametric statistical test designed to detect monotonic trends across ordered treatments or conditions. Developed by Ellis Batten Page in 1963, this test evaluates whether observations follow a predicted ordering pattern when multiple subjects are measured under multiple conditions.

Page’s L test is appropriate when there are at least 3 treatments (conditions), at least 2 subjects (replications), and a hypothesized ordering of treatment effects. The test compares the null hypothesis that all treatment means are equal (m_1 = m_2 = \cdots = m_n) against the alternative hypothesis that they follow a monotonic trend (m_1 \leq m_2 \leq \cdots \leq m_n, with at least one strict inequality).

This implementation uses the SciPy library’s page_trend_test function. The procedure works by ranking observations within each subject (row), summing ranks for each treatment (column), weighting these sums by predicted ranks, and computing the L statistic as the total of these products.

The test statistic L is calculated as:

L = \sum_{j=1}^{n} j \cdot R_j

where R_j is the sum of ranks for treatment j across all subjects, and j represents the predicted rank. For significance testing, SciPy computes the standardized statistic:

\Lambda = \frac{L - E_0}{\sqrt{V_0}}

where E_0 = \frac{mn(n+1)^2}{4} and V_0 = \frac{mn^2(n+1)(n^2-1)}{144}, with m subjects and n treatments. This standardized value is asymptotically normal under the null hypothesis.

Page’s L test has greater statistical power than the Friedman test when the alternative hypothesis specifies a particular trend direction, since Friedman’s test only detects differences without considering order. The function supports exact p-value computation (recommended for small samples) and asymptotic approximation for larger datasets. For further details, see Page’s original paper in the Journal of the American Statistical Association (1963) or the Wikipedia article on Page’s trend test.

This example function is provided as-is without any representation of accuracy.

Excel Usage

=PAGE_TREND_TEST(data, ranked, predicted_ranks, page_method)
  • data (list[list], required): 2D array of shape (m, n) where each row is a subject and each column is a treatment.
  • ranked (bool, optional, default: false): If True, data is already ranked; otherwise, data will be ranked within each row.
  • predicted_ranks (list[list], optional, default: null): 1-row 2D array of predicted ranks for each treatment. If omitted, defaults to [1, 2, …, n].
  • page_method (str, optional, default: “auto”): Method for p-value calculation.

Returns (list[list]): 2D list [[L_stat, p_value, method]], or error string.

Examples

Example 1: Standard Page trend test with default options

Inputs:

data ranked page_method
3 4 3 false auto
2 2 4
3 3 5
1 3 2
2 3 2
2 4 5
1 2 4
3 4 4
2 4 5
1 3 4

Excel formula:

=PAGE_TREND_TEST({3,4,3;2,2,4;3,3,5;1,3,2;2,3,2;2,4,5;1,2,4;3,4,4;2,4,5;1,3,4}, FALSE, "auto")

Expected output:

Result
133.5 0.0018 exact

Example 2: Page trend test with asymptotic p-value calculation

Inputs:

data ranked page_method
3 4 3 false asymptotic
2 2 4
3 3 5
1 3 2
2 3 2
2 4 5
1 2 4
3 4 4
2 4 5
1 3 4

Excel formula:

=PAGE_TREND_TEST({3,4,3;2,2,4;3,3,5;1,3,2;2,3,2;2,4,5;1,2,4;3,4,4;2,4,5;1,3,4}, FALSE, "asymptotic")

Expected output:

Result
133.5 0.0013 asymptotic

Example 3: Page trend test with pre-ranked data

Inputs:

data ranked page_method
1.5 3 1.5 true auto
1.5 1.5 3
1 3 2
1.5 3 1.5
1 2 3
1 2.5 2.5
1 2 3
1 2 3
1 2.5 2.5
1 2 3

Excel formula:

=PAGE_TREND_TEST({1.5,3,1.5;1.5,1.5,3;1,3,2;1.5,3,1.5;1,2,3;1,2.5,2.5;1,2,3;1,2,3;1,2.5,2.5;1,2,3}, TRUE, "auto")

Expected output:

Result
133.5 0.0018 exact

Example 4: Page trend test with custom predicted ranks

Inputs:

data ranked predicted_ranks page_method
4 3 3 false 2 3 1 auto
2 4 2
3 5 3
3 2 1
3 2 2
4 5 2
2 4 1
4 4 3
4 5 2
3 4 1

Excel formula:

=PAGE_TREND_TEST({4,3,3;2,4,2;3,5,3;3,2,1;3,2,2;4,5,2;2,4,1;4,4,3;4,5,2;3,4,1}, FALSE, {2,3,1}, "auto")

Expected output:

Result
133.5 0.0018 exact

Python Code

from scipy.stats import page_trend_test as scipy_page_trend_test

def page_trend_test(data, ranked=False, predicted_ranks=None, page_method='auto'):
    """
    Perform Page's L trend test for monotonic trends across treatments.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.page_trend_test.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        data (list[list]): 2D array of shape (m, n) where each row is a subject and each column is a treatment.
        ranked (bool, optional): If True, data is already ranked; otherwise, data will be ranked within each row. Default is False.
        predicted_ranks (list[list], optional): 1-row 2D array of predicted ranks for each treatment. If omitted, defaults to [1, 2, ..., n]. Default is None.
        page_method (str, optional): Method for p-value calculation. Valid options: Auto, Exact, Asymptotic. Default is 'auto'.

    Returns:
        list[list]: 2D list [[L_stat, p_value, method]], or error string.
    """
    def to2d(x):
        return [[x]] if not isinstance(x, list) else x

    # Validate data
    data = to2d(data)
    if not isinstance(data, list) or len(data) < 2:
        return "Invalid input: data must be a 2D list with at least 2 rows."
    if not isinstance(data[0], list) or len(data[0]) < 3:
        return "Invalid input: data must have at least 3 columns (treatments)."
    try:
        arr = [[float(x) for x in row] for row in data]
    except Exception:
        return "Invalid input: data must contain only numeric values."

    # Validate ranked
    if isinstance(ranked, list):
        ranked = to2d(ranked)
        ranked = ranked[0][0]
    if isinstance(ranked, str):
        ranked = ranked.strip().lower() == "true"
    ranked = bool(ranked)

    # Validate predicted_ranks
    pr = None
    if predicted_ranks is not None:
        predicted_ranks = to2d(predicted_ranks)
        try:
            pr = [float(x) for x in predicted_ranks[0]]
        except Exception:
            return "Invalid input: predicted_ranks must be a 2D list of numeric values."

    # Validate page_method
    if page_method is None:
        page_method = "auto"
    if isinstance(page_method, list):
        page_method = to2d(page_method)
        page_method = str(page_method[0][0])
    page_method = str(page_method).strip().lower()
    if page_method not in ("auto", "exact", "asymptotic"):
        return "Invalid input: page_method must be 'auto', 'exact', or 'asymptotic'."

    try:
        res = scipy_page_trend_test(arr, ranked=ranked, predicted_ranks=pr, method=page_method)
    except Exception as e:
        return f"Error in page_trend_test: {e}"
    return [[float(res.statistic), float(res.pvalue), str(res.method)]]

Online Calculator