*! version 1.0.0 06apr2026

Title

finegray -- Fine-Gray competing risks regression

Syntax

finegray
varlist
[if] [in],
compete(varname)
cause(#)
[options]

Required
compete(varname) event type variable (0=censored, 1, 2, ...)

cause(#) value of compete() for cause of interest

Model
censvalue(#) censoring value in compete(); default is 0

strata(varlist) stratify censoring distribution by groups (numeric only)

SE/Robust
cluster(varname:numvar) adjust SEs for intragroup correlation (numeric only)

norobust report model-based SEs instead of default sandwich estimator

Reporting
noshr report coefficients instead of subdistribution hazard ratios

level(#) set confidence level; default is level(95)

nolog suppress iteration log

Optimization
iterate(#) maximum iterations; default is iterate(200)

tolerance(#) convergence tolerance; default is tolerance(1e-8)

varlist may contain factor variables and interactions; see fvvarlist. Supports i.varname, ib#.varname, c.varname, #, and ## operators. Data must be stset with id(). One observation per subject. Left-truncated (delayed entry) data are supported.

Post-estimation:

finegray_predict
newvar
[if] [in],
[cif xb schoenfeld timevar(varname)]

finegray_phtest
[, time(rank|log|identity) detail]

Description

finegray fits the Fine and Gray (1999) subdistribution hazard model for competing risks data. It estimates subdistribution hazard ratios (SHR) which quantify the effect of covariates on the cumulative incidence of a cause of interest in the presence of competing events.

The estimator uses a native O(np) forward-backward scan algorithm (Kawaguchi et al. 2021) that avoids data expansion entirely, making it substantially faster than stcrreg for large datasets. See Performance under Remarks for benchmarks.

Options

Required

compete(varname) specifies the variable containing event types. Typically coded as 0 = censored, 1 = cause 1, 2 = cause 2, etc. Must be consistent with the stset failure indicator.

cause(#) specifies which value of compete() represents the cause of interest.

Model

censvalue(#) specifies the value in compete() that represents censoring. Default is 0.

strata(varlist) stratifies the Kaplan-Meier censoring distribution estimation by the specified variables. This is appropriate when the censoring mechanism differs across groups (e.g., treatment arms or study sites).

SE/Robust

cluster(varname) adjusts standard errors for intragroup correlation.

norobust reports model-based standard errors from the observed information matrix instead of the default Huber/White/sandwich estimator. The sandwich estimator is the default because the Fine-Gray model uses a pseudo-likelihood, making robust SEs appropriate regardless of model specification.

Reporting

noshr reports coefficients (log subdistribution hazard ratios) instead of exponentiated coefficients (subdistribution hazard ratios).

level(#) specifies the confidence level for confidence intervals. Default is level(95).

nolog suppresses the iteration log.

Optimization

iterate(#) specifies the maximum number of Newton-Raphson iterations. Default is iterate(200).

tolerance(#) specifies the convergence tolerance. Default is tolerance(1e-8).

Remarks

The Fine-Gray model directly models the subdistribution hazard, which is the instantaneous rate of failure from the cause of interest among subjects who have not yet experienced that specific cause. Subjects who experience a competing event remain in the risk set indefinitely with time-dependent weights derived from the Kaplan-Meier estimate of the censoring distribution.

Factor variables and interactions: finegray supports the full Stata factor-variable syntax via fvrevar: i.varname, ib#.varname, c.varname, # (interaction), and ## (full factorial with main effects). Indicator and interaction variables are automatically created with the prefix _fg_ (e.g., _fg_race_2, _fg_race_2Xage for an i.race#c.age interaction). These persist in the dataset for use with finegray_predict. Re-running finegray drops only the finegray-created FV variables recorded from the prior run; it does not wildcard-drop every _fg_* variable in the dataset.

Note: finegray_predict reconstructs factor-variable design columns on demand via fvrevar. This requires that the current data preserve the same factor-level support as the estimation sample. If a factor level is dropped or absent, prediction will fail with an error. The persistent _fg_* columns are retained for convenience but are not required for prediction when the factor support is intact.

Interpretation: A subdistribution hazard ratio (SHR) > 1 indicates that the covariate increases the cumulative incidence of the cause of interest. Unlike cause-specific hazard ratios, SHRs have a direct interpretation in terms of the cumulative incidence function.

Left truncation (delayed entry): finegray supports left-truncated data where subjects enter observation after time 0. Use stset with the enter() option to specify entry times. The censoring distribution and risk sets are computed correctly for delayed entry.

Proportional hazards diagnostic: Use finegray_phtest after estimation for an approximate test of the proportional subdistribution hazards assumption via scaled Schoenfeld residuals. See finegray_phtest for details on the diagonal-only scaling and independent per-variable test structure. Both finegray_phtest and finegray_predict, schoenfeld require the original stset estimation data (_t, _d, and e(sample)); they cannot be run after loading a new dataset. finegray_predict, xb and finegray_predict, cif work on any dataset containing the model covariates.

Margins: margins is supported after finegray for the linear predictor (predict(xb)) in models without factor-variable expansion. For factor-variable models, margins is not supported because the estimation uses generated design columns rather than native Stata factor notation.

Cross-validation against other implementations: finegray is systematically validated against three independent implementations: Stata's stcrreg, R's cmprsk::crr, and R's fastcmprsk::fastCrr. The cross-validation suite (55 tests) covers coefficients, standard errors, log-likelihoods, cumulative incidence functions, baseline hazards, and stratified censoring across real and simulated datasets.

Point estimates (coefficients) and log pseudo-likelihoods are numerically identical across all four implementations. Against cmprsk::crr, coefficients match to 6 decimal places, robust SEs match to 3 decimal places, model-based SEs match to 6 decimal places, and CIF predictions match to 6 decimal places. Against fastcmprsk::fastCrr, coefficients and log-likelihoods match to 6 decimal places, and the baseline cumulative hazard matches to 8 decimal places. Against stcrreg, coefficients match within 1e-4 across all tested configurations including multiple covariate combinations, both causes, factor variables, cluster SEs, and left-truncated data. The strata() option is cross-validated against crr(..., cengroup=); coefficients agree within 0.002 and SEs within 0.3%, reflecting minor differences in how the stratified censoring KM is computed internally.

Technical note on standard errors: The only quantity where implementations diverge is standard errors, and this reflects differences in variance estimation approach rather than errors. finegray (default) and cmprsk::crr both compute IPCW sandwich SEs on the original (unexpanded) data, producing agreement to 3+ decimal places. stcrreg computes sandwich SEs on an expanded dataset; both are valid sandwich estimators but the different computational path produces ~0.5% relative SE differences. finegray with norobust and crr$invinf both report the inverse observed information matrix, matching to 6 decimal places. fastcmprsk::fastCrr uses bootstrap SEs (B=200), a fundamentally different variance estimator; wider divergence (up to ~50%) is expected. When norobust is specified, finegray reports the observed-information variance matrix. This is not a like-for-like replacement for stcrreg's reported SEs.

Performance: The forward-backward scan algorithm is O(np) per Newton-Raphson iteration, compared to O(nDp) for stcrreg, where D is the number of unique event times. Benchmarks on simulated competing risks data (3 covariates, Stata/MP):

N finegray stcrreg Speedup

500 0.04s 1.5s 40x
1,000 0.06s 3.9s 63x
2,000 0.14s 15.9s 114x
5,000 0.27s 96.8s 357x
10,000 0.58s 378.7s 651x

The speedup grows with sample size because stcrreg expands the dataset by the number of unique event times. At registry scale (N=50,000+), finegray completes in under 10 seconds with 3 covariates; stcrreg is not feasible at these sizes.

Limitations: The by: prefix is not supported because finegray requires stset with id(), which is incompatible with by: processing. To fit models on subgroups, use if conditions. Sampling weights (fweight, pweight) are not supported.

References

Fine JP, Gray RJ. A proportional hazards model for the subdistribution of a competing risk. JASA 1999; 94(446): 496-509.

Kawaguchi ES, Shen JI, Suchard MA, Li G. Scalable algorithms for large competing risks data. Journal of Computational and Graphical Statistics 2021; 30(3): 685-693.

Grambsch PM, Therneau TM. Proportional hazards tests and diagnostics based on weighted residuals. Biometrika 1994; 81(3): 515-526.

Examples

Setup

. webuse hypoxia, clear

. gen byte status = failtype

. stset dftime, failure(dfcens==1) id(stnum)

Basic model

. finegray ifp tumsize pelnode, compete(status) cause(1)

Stratified censoring distribution

. finegray ifp tumsize, compete(status) cause(1) strata(pelnode)

Model-based standard errors (default is robust/sandwich)

. finegray ifp tumsize pelnode, compete(status) cause(1) norobust

Log-SHR (no exponentiation)

. finegray ifp tumsize pelnode, compete(status) cause(1) noshr

CIF prediction

. finegray ifp tumsize pelnode, compete(status) cause(1)

. finegray_predict cif_hat, cif

Factor variables (automatic indicator expansion)

. finegray i.pelnode ifp, compete(status) cause(1)

Factor variables with specified base category

. finegray ib1.pelnode ifp, compete(status) cause(1)

Interaction: factor x continuous (full factorial)

. finegray i.pelnode##c.ifp tumsize, compete(status) cause(1)

Interaction: factor x factor

. gen byte ifp_grp = (ifp > 10)

. finegray i.pelnode##i.ifp_grp tumsize, compete(status) cause(1)

Margins (adjusted predictions)

. finegray ifp tumsize pelnode, compete(status) cause(1)

. margins, at(ifp=(0 5 10)) predict(xb)

. margins, dydx(ifp) predict(xb)

Compare with stcrreg (requires different stset)

. stset dftime, failure(status==1) id(stnum)

. stcrreg ifp tumsize pelnode, compete(status == 2)

Stored results

finegray stores the following in e():

Scalars

e(N) number of subjects

e(N_fail) number of cause-of-interest events

e(N_compete) number of competing events

e(N_cens) number of censored observations

e(ll) log pseudo-likelihood

e(ll_0) log pseudo-likelihood, constant-only model

e(chi2) Wald chi-squared

e(p) p-value for model chi-squared

e(df_m) model degrees of freedom

e(converged) 1 if converged, 0 otherwise

e(level) confidence level

e(cause) cause of interest value

e(censvalue) censoring value

e(iterate) maximum iterations

e(tolerance) convergence tolerance

Macros

e(cmd) finegray

e(cmdline) full estimation command as typed

e(predict) finegray_predict

e(depvar) competing events variable name

e(compete) competing events variable name

e(covariates) covariate variable names

e(fvvarlist) original factor-variable specification; if factor variables used

e(strata) censoring stratification variables; if strata() specified

e(clustvar) cluster variable; if cluster() specified

e(vce) variance estimation method

e(title) Fine-Gray competing risks regression

e(marginsok) xb (empty for factor-variable models)

e(properties) b V

Matrices

e(b) coefficient vector (log-SHR)

e(V) variance-covariance matrix

e(basehaz) baseline cumulative subhazard (time, cumhazard)

finegray also records dataset characteristics _dta[_finegray_estimated], _dta[_finegray_compete], _dta[_finegray_cause], and _dta[_finegray_covars]. When factor variables are used it also records _dta[_finegray_fvvars] and _dta[_finegray_fvvarlist]. These persist with the dataset and allow subsequent finegray runs to clean up prior finegray-generated factor-variable columns safely.

Author

Timothy P Copeland, Karolinska Institutet

Version 1.0.0, 2026-04-06

Report bugs and suggestions at

https://github.com/tpcopeland/Stata-Tools

Also see

Online: finegray_predict, finegray_phtest, stcrreg, stcox, stset