Search code examples
rsurvival-analysissurvivalcox

Error when model diagnostics on stratified variable with coxph (survival package) in R


I have a dataset where 3 groups have recieved exposure to different media. One group is exposed to 1 of the 3 media. Therefore, my coxph model is stratified:

# My treatment variable is loaded as a factor.
fullModel <- coxph(Surv(time, status) ~ strata(treatment), data = d) 

When I try to do model diagnostics I get this error:

test.assump <- cox.zph(fullModel)
Error in cox.zph(fullModel) : 
there are no score residuals for a Null model

But, if I remove the strata() argument, I get to run diagnostics on the model:

          chisq df    p
treatment  1.29  2 0.52
GLOBAL     1.29  2 0.52

I've made this example to reproduce my error:

data <- list(time=c(4,3,1,1,2,2,3,2,4,1,3,4), 
             status=c(1,1,1,0,1,1,0,1,1,0,0,1),  
             treatment=c(0,0,0,0,1,1,1,1,2,2,2,2))

cox.test <- coxph(Surv(time, status) ~ strata(treatment), data = data)

test.coxas <- cox.zph(cox.test)
ggcoxzph(test.coxas)

ggcoxdiagnostics(test.coxas, type = "schoenfeld",
                 linear.predictions = F)

Should I do diagnostics without the strata argument? And then use the strata argument after so I can plot the different exposures in a ggsurvplot? Where am I going wrong here?

Thank you in advance for helping me resolve this trouble.


Solution

  • I'm bracketing whether using strata() is the best modeling choice, given what I understand of your application, and focusing on the actual question you asked.

    Schoenfeld residuals are used to diagnose proportional hazard violations a Cox model's covariates. Your model specification has no covariates. Ergo, you have no PH violations to diagnose and potentially correct, which is why cox.zph is throwing a "null model" error, as in "this model only estimates the (Cox model's version of an) intercept term".

    Put differently: Schoenfeld residuals are covariate-specific quantities, so if there are no covariates in the Cox model, there are no Schoenfelds to calculate. cox.zph's calculations involve the Schoenfeld residuals, hence the error.

    Instead, you have a strata() term. Stratifying permits different groups to have a different baseline hazard rate (= the Cox's version of an intercept term, heuristically speaking). There are many reasons you might stratify, but one of them is to correct for possible PH violations—the very issue that's leading you to run cox.zph in the first place. If you keep stratifying on treatment, there are no PH-related model diagnostics for you to run.

    (As an aside: for ggcoxdiagnostics in your MWE, you need to pass in the coxph object, not the cox.zph object.)