R k折交叉验证后调用stepAIC逐步回归提示行数变化错误如何解决?
报错根本原因
这是R语言惰性求值的典型坑,和训练集本身的行数差异无关:
你在循环中构建lm模型时,mod <- lm(z_mara ~ . -1, data = trainCV_sets[[i]]) 这句的调用记录里存储的是trainCV_sets[[i]]这个表达式,而非i对应的当时的实际子集数据。循环结束后全局环境的i值固定为4,你后续调用stepwise/stepAIC时,函数会解析模型调用记录里的data参数,所有模型的训练集都会被解析为trainCV_sets[[4]](12行),但前3个模型初始拟合用的是11行的训练集,拟合子模型时用的是12行数据,因此触发行数不一致的报错。
解决方法
两种方案任选即可:
方案1:构建模型时直接固化拟合数据,避免后续动态解析i
将构建lm的代码修改为:
mod <- lm(z_mara ~ . -1, data = trainCV_sets[[i]], # 显式将当前子集的自变量、因变量直接存入模型对象 x = TRUE, y = TRUE)
x=TRUE和y=TRUE会把拟合用到的变量直接存在lm对象里,stepAIC会优先用这部分数据拟合子模型,不需要再解析调用记录里的data参数。
方案2:调用stepwise时显式传入对应训练集
修改遍历代码,同时传入模型和对应的训练集:
# 用map2同时遍历模型列表和训练集列表 map2(modList, trainCV_sets, ~ stepwise(.x, direction = "backward", criterion = "AIC", data = .y))
修复后的完整可运行代码
library(tidyverse) library(modelr) library(MASS) # 若使用car包的stepwise,替换加载包即可,用法一致 training_pca <- tibble(z_mara = c(0.875112399579427, 1.13894237770963, 0.981180086218575, 1.8299894270253, -0.0977104233331723, -0.86241558837047, -1.40078945237221, 0.030856469562766, -0.0969068802525719, -0.223063143906711, -0.339309042900122, -0.760633464827852, -1.01830294600679, -1.29686454728133, -1.39007554463088), PC1 = c(2.50796906215996, 2.68002216940135, -3.71526007848766, -4.1866795459591, 0.0486434530855795, 0.938304238296873, 0.615097559709769, 4.51822579066407, 0.0667126218105262, -0.287378553280471, 4.56603423346247, -0.933301952142784, -0.216058021757341, 0.0694218190496208, 9.2292656007433), PC2 = c(2.17078441684463, -0.199721476838284, 2.11735035612631, 3.03544498625801, -2.40626489140099, 2.35791076587204, -1.25582416436226, 1.05994935645006, -0.527916055713799, 0.070729476106444, -0.132485078109658, 0.949419002097709, -5.09998831832504, 1.0619915074115, 2.3100848754419), PC3 = c(-0.678144405424994, 1.09058577380406, -1.0176297169444, -1.88552787304444, -1.25338902691145, 0.210499981706639, 0.04477690001186, -1.38969813324165, -0.804920509008458, 0.879138015029564, 1.29938967213637, 0.138188073442918, -5.26695126718185, -2.14797795807358, 1.62335052575001), PC4 = c(-2.3887668089524, 3.97903517088607, 0.867800635964586, -2.03442689569174, 0.13869948487601, -0.0664645238981098, 0.670700717048399, 3.11260554952338, 0.408133658723152, 3.44132931097882, 1.10549707214258, 1.0954984094734, -0.49754510472686, -2.85815085785707, 2.04309500230981), PC5 = c(0.821714377740757, 3.78554017369849, 0.230169453679477, -1.9039365507055, 0.0828762592235243, -1.83817906200712, -2.4669972669382, 1.88139312797292, -1.28458814157848, -1.74987295529079, 0.342015969239523, -0.819381168596516, 1.64847329083668, -3.95311876523071, -0.306975624219868)) set.seed(3654) trainingCV_pca <- crossv_kfold(training_pca, k = 4) trainCV_sets <- vector(mode = "list", length = nrow(trainingCV_pca)) testCV_sets <- vector(mode = "list", length = nrow(trainingCV_pca)) for(i in 1:nrow(trainingCV_pca)) { trainCV_idx <- trainingCV_pca[[1]][[i]][[2]] trainCV_sets[[i]] <- training_pca[trainCV_idx,] testCV_sets[[i]] <- training_pca[-trainCV_idx,] } modList <- vector(mode = "list", length = nrow(trainingCV_pca)) for(i in 1:nrow(trainingCV_pca)) { # 新增x=TRUE y=TRUE固化拟合数据 mod <- lm(z_mara ~ . -1, data = trainCV_sets[[i]], x = TRUE, y = TRUE) modList[[i]] <- mod } # 直接调用即可正常运行,trace=FALSE可关闭逐步过程输出 map(modList, ~ stepAIC(., direction = "backward", criterion = "AIC", trace = FALSE))
内容的提问来源于stack exchange,提问作者a.hesse
相关产品推荐
相关产品推荐

