rms::lrm中使用offset报‘sformula not found’错误的技术问询
问题:rms::lrm使用offset时出现
sformula not found错误 尝试将已开发完成的模型放入lrm框架中,使用validate函数进行bootstrap验证,但引入offset项(已知系数)时出现以下错误:
Error in lrm(Death ~ offset(2 * Age), data = patient_data) : object 'sformula' not found
尽管帮助文档说明offset在rms::lrm中可用,但仍出现该错误。以下是可复现代码:
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) #运行正常 glm(Death ~ Age, family = "binomial", data = patient_data) #运行正常 glm(Death ~ offset(2*Age), family = "binomial", data = patient_data) #运行正常 lrm(Death ~ offset(2*Age),data = patient_data) #报错
补充内容
目前暂无该bug的官方解决方案,提供一个替代方案,请求验证代码正确性:
# 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")
解答
错误原因
这个错误是rms::lrm的内部逻辑bug:当模型仅包含offset项、没有待估计的参数时,lrm无法正确生成后续流程依赖的sformula对象。glm没有这个限制,因此仅含offset的模型能正常运行,而lrm会报错。
替代方案代码验证
该替代方案逻辑正确,可实现bootstrap验证需求,具体分析如下:
- 函数参数符合要求:
fBootMetrics的参数匹配boot包的要求,第一个参数接收原始数据,第二个参数接收bootstrap样本的索引,能正确生成bootstrap样本。 - 模型拟合正确:使用
glm(Death ~ 0 + offset(2 * Age), ...)去掉截距项,适配仅含固定offset的模型场景,拟合逻辑合理。 - 验证指标计算正确:通过
rms::val.prob分别计算bootstrap样本上的表观性能、模型在原始数据上的性能,两者差值用于评估乐观偏差,这是bootstrap验证的常规做法。 - 兼容性处理到位:代码中
as.numeric(Death) - 1的处理,兼容Death为因子类型的场景,即使当前测试数据中Death是0/1数值,也不会影响结果。 - 结果整理正确:最后将bootstrap结果赋值并修改列名,便于后续分析。
综上,该替代方案可有效避开lrm的bug,完成bootstrap验证需求。
内容的提问来源于stack exchange,提问作者Rover Eye
相关产品推荐
相关产品推荐

