R语言K折交叉验证绘制各折ROC曲线及closure报错解决
报错原因
- 核心触发原因是数据集列名和模型公式不匹配:构造
for_lift时你将观测结局列命名为Class,但循环内调用lift()时使用的公式为diabetes ~ rf,单折数据集fold_df中不存在名为diabetes的列,R会向上寻址找到环境中类型为闭包(函数)的同名对象,导致lift()返回异常结果,后续用$data对异常结果取子集时就会触发该报错。 - 次要可能诱因:未提前加载caret包导致
lift()函数寻址错误,也会触发同类报错。
修正实现方案
修正列名匹配问题,同时优化绘图逻辑,增加参考线、平均ROC曲线提升可读性,完整可运行代码如下:
# 提前加载依赖包,避免函数寻址错误 library(caret) library(ggplot2) library(dplyr) # 交叉验证控制参数无需修改 t_control <- trainControl( method = "cv", number = 5, classProbs = T, savePredictions = T, summaryFunction = twoClassSummary ) model_forest <- caret::train(diabetes ~., data = train_set, method = "rf", metric = "ROC", trControl = t_control) # 修正:结局列保持和原数据一致命名为diabetes,和后续lift公式匹配 # 正例概率直接取pos类对应列,避免因子水平顺序变动导致取错概率 for_lift <- data.frame( diabetes = model_forest$pred$obs, rf = model_forest$pred$pos, resample = model_forest$pred$Resample ) lift_df <- data.frame() for (fold in unique(for_lift$resample)) { fold_df <- dplyr::filter(for_lift, resample == fold) # 列名匹配后lift可正常运行 lift_obj_data <- lift(diabetes ~ rf, data = fold_df, class = "pos")$data lift_obj_data$fold = fold lift_df = rbind(lift_df, lift_obj_data) } # 计算整体平均ROC坐标 lift_overall <- lift(diabetes ~ rf, data = for_lift, class = "pos")$data lift_overall$fold <- "平均" plot_df <- rbind(lift_df, lift_overall) # 绘图 ggplot(plot_df) + geom_abline(linetype = "dashed", color = "gray50") + # 添加随机猜测参考线 geom_line(aes(1 - Sp, Sn, color = fold, linewidth = fold)) + # 平均曲线加粗突出显示 scale_linewidth_manual( values = c("平均" = 1.2, setNames(rep(0.7, length(unique(lift_df$fold))), unique(lift_df$fold))), guide = "none" ) + scale_color_discrete(guide = guide_legend(title = "交叉验证折数")) + labs(x = "1 - 特异度(假阳性率)", y = "敏感度(真阳性率)", title = "5折交叉验证各折ROC曲线") + theme_bw()
代码说明
- 修正了
for_lift构造时的列名错误,保证lift()公式中的变量名和数据集中列名完全一致,从根源解决闭包取子集的报错 - 正例概率直接取
pos类对应列,避免因子水平顺序变化导致取错概率的问题 - 新增随机猜测参考对角线、整体平均ROC曲线,绘图可读性更强
- 显式加载所有依赖包,避免函数寻址错误
内容的提问来源于stack exchange,提问作者PicaPython
相关产品推荐
相关产品推荐

