调用riskRegression时rbindlist列数不匹配错误的原因与解决
问题:使用riskRegression的Score函数时rbindlist报错
我在量化两个独立的病因特异性Cox回归模型预测性能时,调用riskRegression包的Score函数遇到了rbindlist相关错误,疑似和fill=TRUE参数有关。
模型代码
library(survival) a_t7_n8_cmprsk <- coxph(Surv(event.tid, event == 1) ~ t7, x = TRUE, data = df) a_t0_n8_cmprsk <- coxph(Surv(event.tid, event == 1) ~ n8, x = TRUE, data = df)
Score函数调用代码
library(riskRegression) u_n8_cmprsk <- Score(list("t7_n8" = a_t7_n8_cmprsk, "t0_n8" = a_t0_n8_cmprsk), Hist(event.tid, event == 1) ~ 1, data = df, times = c(12, 30, 60), plots=c("cal"), B = 100, seed = 1, split.method = "loob", metrics = c("auc","brier"))
错误信息
Error in rbindlist(foreach::foreach(b = 1:B, .export = exports, .packages = "data.table", : Item 79 has 2 columns, inconsistent with item 1 which has 9 columns. To fill missing columns use fill=TRUE.
数据样本
df <- structure(list(t7 = c("pT1", "pT4a", "pT1", "pT4a", "pT1", "pT2", "pT2", "pT2", "pT3", "pT1", "pT2", "pT2", "pT1", "pT3", "pT3", "pT2", "pT2", "pT1", "pT1", "pT1", "pT4a", "pT1", "pT4a", "pT3", "pT1", "pT2", "pT2", "pT4a", "pT4a", "pT1", "pT4a", "pT2", "pT4a", "pT3", "pT1", "pT2", "pT4a", "pT1", "pT2", "pT1", "pT1", "pT2", "pT1", "pT2", "pT1", "pT2", "pT3", "pT4a", "pT2", "pT4a"), n8 = c("pN2b", "pN0", "pN0", "pN0", "pN0", "pN0", "pN0", "pN0", "pN3b", "pN0", "pN0", "pN1", "pN1", "pN3b", "pN0", "pN0", "pN1", "pN0", "pN0", "pN2b", "pN0", "pN3b", "pN3b", "pN3b", "pN0", "pN0", "pN2b", "pN3b", "pN1", "pN0", "pN0", "pN0", "pN3b", "pN3b", "pN2b", "pN0", "pN0", "pN0", "pN3b", "pN1", "pN0", "pN1", "pN3b", "pN0", "pN3b", "pN0", "pN3b", "pN0", "pN0", "pN1"), event.tid = c(82.4, 23.9, 20.9, 0.4, 6.7, 124.2, 42.4, 38.8, 5.1, 6.5, 40.5, 15.3, 60.3, 32.5, 62.9, 16.8, 14.8, 141, 63.4, 97.3, 13.2, 5.4, 134, 19.1, 59.8, 179.5, 2.6, 130.7, 18.5, 40.5, 13.7, 52.9, 2.4, 9.3, 94.5, 33.5, 79.3, 37.7, 12.7, 5.9, 98.5, 0.7, 17.5, 81.7, 24.4, 33.5, 3.1, 3.1, 84.3, 7.9), event = c(0, 1, 0, 2, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 1, 0, 1, 0, 0, 2, 1, 1, 0, 2, 1, 2, 0, 1, 0, 2, 0, 0, 1, 0, 1, 2, 0, 1)), row.names = c(NA, -50L), class = "data.frame", na.action = structure(262:446, names = c("262", "263", "264", "265", "266", "267", "268", "269", "270", "271", "272", "273", "274", "275", "276", "277", "278", "279", "280", "281", "282", "283", "284", "285", "286", "287", "288", "289", "290", "291", "292", "293", "294", "295", "296", "297", "298", "299", "300", "301", "302", "303", "304", "305", "306", "307", "308", "309", "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", "320", "321", "322", "323", "324", "325", "326", "327", "328", "329", "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", "340", "341", "342", "343", "344", "345", "346", "347", "348", "349", "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", "360", "361", "362", "363", "364", "365", "366", "367", "368", "369", "370", "371", "372", "373", "374", "375", "376", "377", "378", "379", "380", "381", "382", "383", "384", "385", "386", "387", "388", "389", "390", "391", "392", "393", "394", "395", "396", "397", "398", "399", "400", "401", "402", "403", "404", "405", "406", "407", "408", "409", "410", "411", "412", "413", "414", "415", "416", "417", "418", "419", "420", "421", "422", "423", "424", "425", "426", "427", "428", "429", "430", "431", "432", "433", "434", "435", "436", "437", "438", "439", "440", "441", "442", "443", "444", "445", "446"), class = "omit"))
回答
1. 错误原因
这个错误的核心是**留一交叉验证(loob)**的迭代过程中,某一轮生成的结果数据框列数与其他轮次不一致:
- 两个Cox模型分别基于
t7和n8分类变量,当留一验证排除的样本对应的分类水平在剩余数据中完全消失时,模型拟合后的参数或性能指标列数会减少; - 比如某轮排除样本后,
t7的某个水平(如pT4a)在剩余数据中无记录,对应模型参数会缺失,导致该轮结果列数和其他轮次不匹配; riskRegression内部用rbindlist合并所有迭代结果时,默认要求所有数据框列数一致,因此抛出列数不匹配的错误。
2. 修复方法
有两种可行的修复方案:
方案1:更换交叉验证方法(优先推荐)
放弃split.method = "loob",改用K折交叉验证,避免单样本排除导致的分类水平缺失问题:
u_n8_cmprsk <- Score(list("t7_n8" = a_t7_n8_cmprsk, "t0_n8" = a_t0_n8_cmprsk), Hist(event.tid, event == 1) ~ 1, data = df, times = c(12, 30, 60), plots=c("cal"), B = 100, seed = 1, split.method = "cv", k = 10, # 设置10折交叉验证 metrics = c("auc","brier"))
方案2:修改包内部rbindlist调用(需谨慎)
如果必须使用留一验证,可修改Score函数内部的rbindlist调用,添加fill=TRUE参数兼容列数不一致的情况:
- 执行
trace(riskRegression::Score, edit=TRUE)打开函数源码编辑界面; - 找到调用
rbindlist的位置,将rbindlist(...)修改为rbindlist(..., fill=TRUE); - 保存修改后重新运行代码。
此方法属于修改包内部逻辑,可能影响其他功能稳定性,仅在必须使用留一验证时采用。
内容的提问来源于stack exchange,提问作者cmirian
相关产品推荐
相关产品推荐

