maxcombo_test()

MaxCombo test: maximum of multiple weighted log-rank Z-statistics.

Usage

Source

maxcombo_test(
    surv,
    group=None,
    *,
    data=None,
    case_weights=None,
    weights=None,
    strata=None,
)

The MaxCombo test evaluates survival differences using several Fleming-Harrington weight functions simultaneously and takes the largest absolute Z-statistic as the test statistic. This makes it robust to unknown treatment-effect timing. When the effect is immediate, the standard log-rank (rho=0, gamma=0) dominates. When the effect is delayed, the late-emphasis weight (rho=0, gamma=1) dominates. The MaxCombo adapts automatically.

When to use: When the proportional hazards assumption may not hold and you do not know in advance whether the treatment effect will be early, late, or sustained. This is common in immunotherapy and oncology trials where delayed effects are expected but not guaranteed.

Parameters

surv: Surv | Outcome | str

A Surv response object (right-censored or counting-process). An Outcome or a formula string such as 'Surv(time, status == 2) ~ sex' is also accepted, with its columns read from data. The right-hand side names the group column(s) and strata(x) terms set strata.

group: Any = None

Group labels, one per observation. Must have exactly two unique levels.

weights: list[tuple[float, float]] | None = None

List of (rho, gamma) tuples defining the Fleming-Harrington weight functions. Defaults to the standard four-weight combo: [(0, 0), (1, 0), (0, 1), (1, 1)], covering unweighted, early-emphasis, late-emphasis, and middle-emphasis tests.

strata: Any = None

Optional stratifying factor. When provided, each weighted test is stratified (computed within each stratum, then combined).

data: Any = None

A data frame (pandas, Polars, PyArrow, DuckDB, a lazy frame, …) holding the columns named by the response, group, and strata. When surv is an Outcome or a formula, rows with a missing value in any column used are dropped first, along with the matching rows of any arrays passed alongside.

case_weights: Any = None
Case weights, one per row (a column name in data, or an array). Must be finite and strictly positive. Default is None (all weights 1).

Returns

MaxComboResult

A result object with attributes:

  • statistic: The maximum absolute Z-statistic across all weight functions.
  • p_value: P-value from the multivariate normal distribution.
  • z_statistics: Dictionary mapping each (rho, gamma) tuple to its Z-statistic.
  • correlation: Correlation matrix between the Z-statistics under H0.
  • method: Description of the test.

Details

The MaxCombo test is based on the joint distribution of the standardized weighted log-rank statistics under H0. Under the null hypothesis of equal survival, the Z-statistics are asymptotically multivariate normal with mean zero and a correlation matrix determined by the shared risk-set structure. The p-value is computed as

p = P\bigl(\max_j |Z_j| \ge T_{\mathrm{obs}}\bigr) = 1 - P\bigl(\text{all } |Z_j| < T_{\mathrm{obs}}\bigr),

where the probability is evaluated under the multivariate normal using Sobol quasi-Monte Carlo integration.

References

Lee S.H. (2007). On the versatility of the combination of the weighted log-rank statistics. Computational Statistics & Data Analysis, 51(12), 6557-6564.

Examples

Test whether survival differs between the two sexes in the lung dataset using the default four-weight MaxCombo:

import greenwood as gw

lung = gw.load_dataset("lung", backend="polars")

result = gw.maxcombo_test("Surv(time, status) ~ sex", data=lung)
result
MaxComboResult(statistic=3.5657, p_value=0.0009956, weights=[(0, 0), (1, 0), (0, 1), (1, 1)])

Examine which weight function produced the largest signal:

result.z_statistics
{(0, 0): 3.21352484896035,
 (1, 0): 3.565690872910549,
 (0, 1): 1.8601032675878904,
 (1, 1): 2.7685344459841996}

Use a custom weight set focusing on standard and delayed effects:

gw.maxcombo_test("Surv(time, status) ~ sex", weights=[(0, 0), (0, 1)], data=lung)
MaxComboResult(statistic=3.2135, p_value=0.002224, weights=[(0, 0), (0, 1)])