PolyGenius
Contents

evaluate$stratification

Score-band stratification for PRS models

evaluate$stratification() asks how the outcome changes across percentile bands of each model's score. It reports the outcome in every band and contrasts each band with a reference band, adjusted for the covariates.

Usage

evaluate$stratification(
  data,
  outcomes,
  covariates = NULL,
  scores.layer = X,
  split.by = NULL,
  quantiles = c(0.2, 0.8),
  reference = "lowest",
  conf.level = 0.95,
  p.adjust.method = "BH"
)

Arguments

ArgumentDescription
dataA [PolyGeniusStudy](/reference/polygeniusstudy/). Holds the score layer and the sample columns the other arguments name. It is not modified.
outcomesUnquoted outcome expression resolved from data: a bare column, an expression such as status == "case", an [outcome()](/reference/outcome/) descriptor, or a c() or list() of these whose names label the outcomes. The type is binary or continuous, inferred from the values unless the descriptor sets it. A [surv()](/reference/surv/) outcome aborts.
covariatesUnquoted covariate expression resolved from data, such as c(age, sex, PC1), or NULL (default). A character vector aborts. The covariates adjust the contrasts only; the band rates and means are unadjusted.
scores.layerUnquoted name of an existing score layer, default X. The layer is used as supplied: nothing is scored or standardised here.
split.byUnquoted expression naming factor, character or logical sample columns, or NULL (default). Adds rows for each level beside the overall stratum = "all" rows. A level named "all" aborts. Every level reuses the bands cut on the overall sample; the contrasts are fitted within each level.
quantilesNumeric vector, default c(0.2, 0.8). The inner band breaks as score percentiles, strictly increasing and inside (0, 1); anything else aborts. k values give k + 1 bands, so the default gives "0-20%", "20-80%" and "80-100%".
reference"lowest" (default) or a band label such as "20-80%". The band every other band is contrasted against. A label that matches no band aborts.
conf.levelNumeric scalar in (0, 1), default 0.95.
p.adjust.methodOne of stats::p.adjust.methods, default "BH". Applied within analysis, outcome, metric and stratum. Only the contrasts carry p-values, so one family spans every model and non-reference band of an outcome, metric and stratum.

Value

A PolyGeniusEvaluation following the schema-evaluation schema. $results has the columns listed in evaluate, one row per outcome, model, stratum and band, plus one contrast row per non-reference band:

  • band rows: outcome.rate (binary) or outcome.mean (continuous), with tier the band, tier.ref and pval NA, and the band's n and n.events;
  • contrast rows: odds.ratio (binary) or mean.difference (continuous), with tier the band, tier.ref the reference band, a Wald pval, and the n and n.events of the fitted sample -- a degenerate band's own contrast row, every contrast row when the reference band is degenerate or is the only non-degenerate band, a contrast row after a fit error, and a contrast row whose band dummy was dropped as collinear, all carry that band's own n and n.events instead.

model.ref is NA throughout, and n.events is NA for a continuous outcome. There are no artifacts. $diagnostics records degenerate bands and fit warnings.

Details

Complete cases, strata and multiple testing follow the shared rules in evaluate.

Bands. Bands are cut once per outcome and model, on that pair's overall complete-case sample, at the score quantiles c(0, quantiles, 1) (stats::quantile(), type 7). The same breaks are reused in every split.by level. A score equal to a break goes to the lower band. Duplicated breaks, from heavily tied scores, leave a band empty. Each band is labelled by its percentile range, "<lo>-<hi>%", and the label is the row's tier. Percentiles drop trailing zeros, as in "2.5-10%". Every band keeps its row; an empty band has n = 0 and an NA estimate.

Per band. A binary outcome gives outcome.rate, the band's case fraction, with a Wilson score interval. A continuous outcome gives outcome.mean whenever the band is non-empty, with a t interval; a band of fewer than two, or of constant, values keeps outcome.mean but gets an NA interval, recorded in $diagnostics. These rows are not adjusted for the covariates, carry no p-value, and report the band's own n and n.events.

Contrasts. One stats::glm() (binomial, logit link) or stats::lm() is fitted per outcome, model and stratum, of the outcome on the band plus the covariates, with the reference band as the reference level. Each non-reference band gets one row: odds.ratio on the exp scale for a binary outcome, mean.difference for a continuous one. Intervals and p-values are Wald: normal for a binary outcome, t on the residual degrees of freedom for a continuous one. tier names the band and tier.ref the reference band. The reference band gets no contrast row.

Degenerate bands. The contrast of an empty band, or of a binary band with no cases or no non-cases, is NA; the band is left out of the fit. Every contrast of a model and stratum is NA, with no fit attempted, when the reference band is degenerate or it is the only non-degenerate band; a fit error gives the same NA result, tagged with the error text. A band whose dummy is dropped from the fit as collinear also gets an NA contrast row, on its own. Each case is recorded in $diagnostics, along with any fit or prop.test() warning, deduplicated per cell.

Interpretation

outcome.rate is the case fraction of the analysed sample. Under case-control ascertainment it is not an absolute risk, and a ratio of two band rates is not a relative risk.

The odds ratio is conditional on the covariates. Odds ratios are non-collapsible, so it can differ from the unadjusted odds ratio even without confounding.

Bands are percentiles of the analysed sample, not of a reference population. The same label covers a different score range in another cohort or for another model.

Under split.by, each level keeps the overall cut. A level's bands are not its own percentiles and need not hold the nominal share of its samples.

Examples

strat <- evaluate$stratification(data, outcomes = case, covariates = c(age, sex, PC1))

# Top and bottom deciles against the middle 80%, within each sex.
strat <- evaluate$stratification(
  data,
  outcomes   = case,
  covariates = c(age, PC1),
  split.by   = sex,
  quantiles  = c(0.1, 0.9),
  reference  = "10-90%"
)
strat$results

See Also

evaluate$profile(), which runs this with the other components; visualize$evaluate$stratification() plots the contrasts by band.

Other evaluate-components: evaluate, evaluate.association(), evaluate.compare(), evaluate.incremental(), evaluate.performance(), evaluate.profile(), evaluate.redundancy(), evaluate.select()

Aliases: evaluate.stratification, evaluate$stratification