Reuse a nested case-control control set for a second endpoint

Description

Prepares a nested case-control (NCC) sample drawn for one (primary) endpoint so it can be reused to fit a weighted Cox model for a different (secondary) endpoint, sharing the single sampled control set. The sampled controls keep their primary Samuelsen inclusion weights 1/π_j (the inclusion probability is a property of the sampling, not of the endpoint analysed), and the secondary endpoint’s cases that were not already drawn into the sample are augmented from the full Phase-1 cohort with weight 1 (every case of an analysed endpoint is ascertained with probability 1). The result feeds straight into matcha(design = nested_cc(…), estimator = “ipw_cox”) with the secondary endpoint as outcome.

Usage

reuse_ncc_endpoint(ncc, cohort, time, event)

Arguments

ncc A data.table or data.frame from sample_ncc() with incl_prob = TRUE. Must contain .cohort_row, ipw_weight, set, case, and risk_time, plus the cohort columns (carried by sample_ncc()) and a binary column for the secondary event.
cohort A data.frame or data.table — the full Phase-1 cohort from which ncc was drawn. Used to recover the secondary endpoint’s cases that were not sampled. NULL is rejected with matchatr_missing_phase1.
time A single character string naming the cohort follow-up / event-time column (the same column passed to nested_cc(time = …)). Augmented cases take their risk_time from it. Must be present in cohort.
event A single character string naming the secondary endpoint’s binary indicator column in cohort (logical, two-level factor, or numeric 0/1) with at least one case. The same column must be present in ncc (it is, as a carried cohort column) and is passed as outcome to matcha().

Details

Nested case-control studies often record several endpoints in the same cohort. Classical (matched) analysis (Phase 5) ties each control to its case’s failure time, so a control set sampled for one endpoint cannot serve another. The IPW reformulation breaks the matching: the union of cases and controls is treated as a biased cohort subsample weighted by inverse inclusion probability, which makes control reuse across endpoints legitimate (Samuelsen 1997; Saarela, Kulathinal, Arjas & Läärä 2008; Støer & Samuelsen 2012).

The reuse semantics are:

  • Controls keep their primary inclusion weight 1/π_j. π_j is the probability the subject was drawn as a control during the primary risk-set sampling; it does not depend on which endpoint is later analysed, so reusing the primary weight is the theoretically correct inverse-sampling-probability weight.

  • Secondary-endpoint cases are ascertained with probability 1, hence weight 1. Those already present in the sample (drawn as a primary case or as a control) keep their row; those absent are augmented from the cohort, each as its own singleton risk set (a case with no sampled controls).

  • Primary-endpoint cases are competing events for the secondary analysis. They were ascertained by the primary sampling, so they also keep weight 1; the ipw_cox engine enforces this when it builds the deduplicated analysis sample.

When the primary sample already contains every secondary-endpoint case — for example when the NCC was drawn on the union "any-failure" event so all endpoints’ cases were ascertained at once — no augmentation is needed and the input is returned unchanged. In that shared-control case the secondary analysis can also be run directly with matcha(ncc, outcome = “<secondary>”, estimator = “ipw_cox”).

This function does not recompute inclusion probabilities; the secondary endpoint reuses the primary π_j attached by sample_ncc(incl_prob = TRUE). The robust Lin-Wei sandwich variance the ipw_cox engine reports treats the weights as fixed (the standard, slightly conservative treatment).

Value

A data.table with the same columns as ncc: the original NCC rows followed by one augmented row per previously unsampled secondary-endpoint case (weight 1, case = 1, its own set id beyond the sampled sets). The secondary cases’ ipw_weight is set to 1 throughout. Ready for matcha(design = nested_cc(strata = “set”, time = time), estimator = “ipw_cox”) with outcome = event.

References

Saarela O, Kulathinal S, Arjas E, Läärä E (2008). Nested case-control data utilized for multiple outcomes: a likelihood approach and alternatives. Statistics in Medicine 27(28):5991-6008.

Støer NC, Samuelsen SO (2012). Comparison of estimators in nested case-control studies with multiple outcomes. Lifetime Data Analysis 18(3):261-283.

See Also

sample_ncc(), compute_ncc_weights(), matcha(), nested_cc()

Other sampling: compute_ncc_weights(), sample_ncc(), sample_ncc_counter_matched()

Examples

library("matchatr")

set.seed(1)
t1 <- rexp(600, 0.05)
t2 <- rexp(600, 0.05)
tau <- 6
tt <- pmin(t1, t2, tau)
cause <- ifelse(tt >= tau, 0L, ifelse(t1 < t2, 1L, 2L))
cohort <- data.frame(
  id = 1:600,
  t  = tt,
  d1 = as.integer(cause == 1L),   # primary endpoint
  d2 = as.integer(cause == 2L),   # secondary endpoint
  x  = rbinom(600, 1, 0.4)
)
ncc <- sample_ncc(cohort, time = "t", event = "d1", m = 3, incl_prob = TRUE)

# Reuse the one control set for the secondary endpoint
ncc2 <- reuse_ncc_endpoint(ncc, cohort = cohort, time = "t", event = "d2")
fit2 <- matcha(ncc2, outcome = "d2", exposure = "x",
               design = nested_cc(strata = "set", time = "t"),
               estimator = "ipw_cox")
contrast(fit2)
<matchatr_result>
 Estimator:  ipw_cox  (engine: ipw_cox)
 Estimand:   hazard ratio
 Contrast:   Hazard ratio
 CI method:  model
 N:          451

Contrasts:
   comparison  estimate       se  ci_lower ci_upper
       <char>     <num>    <num>     <num>    <num>
1:          x 0.8360695 0.166547 0.5658235 1.235389