rlogistic-regression

Offsetting in rms::lrm ... error: sformula not found?


I am trying to fit a model into an lrm framework so I can bootstrap it with validate. The model has already been developed elsewhere. However, when I use an offset term to account for coefficients already known, I get an error:

Error in lrm(Death ~ offset(2 * Age), data = patient_data) : 
  object 'sformula' not found

Do offsets not work in rms::lrm even though the help file explicitly says they do?

library(rms) 

patient_data <- data.frame(
  PatientID = 1:1000,
  Death = sample(c(0, 1), size = 1000, replace = TRUE),
  Age = round(runif(1000, min = 20, max = 90), 1)
  )

lrm(Death~Age, data = patient_data) #works fine
glm(Death ~ Age), family = "binomial", data = patient_data) #works fine
glm(Death ~ offset(2*Age), family = "binomial", data = patient_data) #works fine

lrm(Death ~ offset(2*Age),data = patient_data) #ERROR

EDIT

While there is no solution for the bug in the code, there is a workaround (someone double check the code?)

# Define the function which will be applied to each bootstraped sample. 
# Note, boot() will output the original data and a list of indices to construct 
# bootstrapped sample

fBootMetrics <- function(tblOrgData, intIndex) {
  
  # Create a bootstrap sample using the provided indices
  tblBootData <- tblOrgData[intIndex, ]
  
  # Fit the logistic regression model on the bootstrap sample
  # The model uses coefficients from the above LASSO penalised model
  mdlDeathBoot <- glm(
    Death ~ 0 + offset(2 * Age),
    family = "binomial",
    data = tblBootData
  )
  
  # Obtain predicted probabilities on the bootstrap sample (apparent) and test
  pred_boot <- predict(mdlDeathBoot, type = "response", newdata = tblBootData)
  pred_org  <- predict(mdlDeathBoot, type = "response", newdata = tblOrgData)
  # Convert Death to numeric and subtract 1 as the factor levels are "1" and "2"
  y_boot <- as.numeric(tblBootData$Death) - 1
  y_org  <- as.numeric(tblOrgData$Death) - 1
  
    return(rms::val.prob(pred_boot, y_boot, pl = FALSE)[c("Dxy", "Intercept", "Slope")] - rms::val.prob(pred_org, y_org, pl = FALSE)[c("Dxy", "Intercept", "Slope")])
}


boot(data = patient_data,
     statistic = fBootMetrics,
     R = 50)$t -> tblMdlPerformance

colnames(tblMdlPerformance) <- c("Dxy", "Intercept", "Slope")

Solution

  • As for OP's actual question Do offsets not work in rms::lrm, it seems like the comment by the rms author here is still true:

    looks like a bug. lrm only seems to support offset if there are other covariates in the model and you are not suppressing the intercept.

    We may check this by creating a toy covariate and add it to your lrm formula:

    patient_data$x = runif(1000)
    lrm(Death ~ x + offset(2*Age), data = patient_data)
    

    Indeed, this works.


    A potential solution is given here: Error using offset argument in an intercept only model in lrm function R, from rms package; try lrm.fit:

    with(patient_data, lrm.fit(y = Death, offset = 2*Age))