grays_test()

Compare cumulative incidence functions across groups using Gray’s test.

Usage

Source

grays_test(
    surv,
    group,
    *,
    cause=1,
)

Gray’s test (1988) is the competing-risks analogue of the log-rank test. While the log-rank test compares overall survival across groups, Gray’s test compares the cumulative incidence function (CIF) for a specific cause across groups, properly accounting for competing events.

The test uses the subdistribution hazard framework: subjects who experience a competing event remain in the risk set with inverse-probability-of-censoring weights, reflecting the fact that they can no longer experience the target cause but still contribute information about its cumulative incidence.

Parameters

surv: Surv

A multi-state Surv response built with Surv.multistate(). Must have at least two causes. Event codes are 0 for censoring and 1..K for causes.

group: Any

Group labels, one per observation. Can be a Narwhals series, 1-D array, or Python sequence. Must have the same length as surv. At least two groups are required.

cause: int | str = 1
The cause of interest to compare across groups. Can be a state label (string) or an integer cause code (1-indexed). Default is 1 (the first cause).

Returns

TestResult

A result object with attributes:

  • statistic: Chi-square test statistic.
  • df: Degrees of freedom (number of groups minus one).
  • p_value: Upper-tail chi-square p-value.
  • method: "Gray's test" with the cause label.
  • observed: Dictionary mapping group labels to observed event counts.
  • expected: Dictionary mapping group labels to expected event counts.

Details

Gray’s test differs from the log-rank test applied to cause-specific hazards. The log-rank test on cause-specific hazards answers “do the cause-specific hazard rates differ?” while Gray’s test answers “do the cumulative incidence functions differ?” These can give different conclusions because the CIF depends on all cause-specific hazards, not just the target one.

The test uses the same IPCW weighting as the Fine-Gray model: subjects with competing events before time t contribute weight G(t-)/G(Ti-), where G is the Kaplan-Meier estimate of the censoring distribution.

Examples

Test whether the cumulative incidence of plasma-cell malignancy (pcm) differs between sexes in the mgus2 dataset:

import greenwood as gw

mg = gw.load_dataset("mgus2", backend="pandas")
etime = mg["ptime"].where(mg["pstat"] == 1, mg["futime"])
cause = mg["pstat"].where(mg["pstat"] == 1, 2 * mg["death"])
cr = gw.Surv.multistate(etime, event=cause, states=("pcm", "death"))

gw.grays_test(cr, group=mg["sex"], cause="pcm")
TestResult(method="Gray's test (cause='pcm')", statistic=1.1945, df=1, p_value=0.2744)

Test the other cause (death) across groups:

gw.grays_test(cr, group=mg["sex"], cause="death")
TestResult(method="Gray's test (cause='death')", statistic=11.6513, df=1, p_value=0.0006416)