使用TidyModels构建随机森林回归模型时交叉验证出现缺失数据错误的技术问询
我来帮你拆解这个问题,这种情况在使用分层交叉验证结合TidyModels时其实挺常见的,咱们一步步分析原因和解决办法:
可能的原因
1. 交叉验证折的数据源未正确处理缺失值
你提到已经用na.omit()处理了train_data_test的缺失值,但创建交叉验证折用的是training_data——这两个数据集是不是同一个?如果training_data没有经过缺失值处理,那折里的子集自然会带有NA,导致拟合时出错。
2. 分层交叉验证导致因子水平分布不均
你用了strata = LEAD_TIME_ACTUAL_BUSINESS_DAYS做分层抽样,可能会出现某个折的训练子集里,某个因子变量(比如CONFIGURATION或STR_RGN_NBR)的部分水平完全消失。而TidyModels在交叉验证时,每个折都会基于该折的训练子集重新预处理数据:如果测试子集里出现了训练子集没有的因子水平,默认会被转为NA,进而触发缺失值错误。
3. 隐性缺失值未被识别
虽然你用profile_missing()确认了无NA,但要注意:数据源中的'00'或双0如果是字符串类型,会不会被某些预处理步骤误判为缺失值?或者有没有列存在空字符串这类隐性缺失?
解决办法
1. 确保交叉验证折使用清理后的数据集
先对创建折的数据源做缺失值处理,再生成交叉验证折:
# 第一步:清理训练集的缺失值 training_data_clean <- training_data %>% na.omit() # 第二步:用清理后的数据集创建分层交叉验证折 lead_time_folds <- vfold_cv(training_data_clean, v = 5, strata = LEAD_TIME_ACTUAL_BUSINESS_DAYS)
2. 在Recipe中处理因子水平的未知情况
在你的配方中添加step_unknown(),将测试子集里未见过的因子水平转为统一的"unknown",避免生成NA:
lead_time_recipe <- recipe(LEAD_TIME_ACTUAL_BUSINESS_DAYS ~ ., data = training_data_clean) %>% step_unknown(all_nominal_predictors()) # 处理所有分类预测变量的未知水平 step_corr(all_numeric_predictors()) # 你的其他预处理步骤 # 其他步骤...
如果需要标记新出现的水平而非合并,也可以用step_novel()来保留这些新水平作为单独类别。
3. 验证每个交叉验证折的子集
可以用以下代码检查每个折的训练和测试子集是否真的没有NA,精准定位问题:
# 检查所有折的训练子集是否有NA lead_time_folds$splits %>% purrr::map(function(split) { train_subset <- training(split) na_cols <- which(sapply(train_subset, function(col) any(is.na(col)))) if(length(na_cols) > 0) { cat("训练子集存在NA的列:", names(train_subset)[na_cols], "\n") } }) # 检查所有折的测试子集是否有NA lead_time_folds$splits %>% purrr::map(function(split) { test_subset <- testing(split) na_cols <- which(sapply(test_subset, function(col) any(is.na(col)))) if(length(na_cols) > 0) { cat("测试子集存在NA的列:", names(test_subset)[na_cols], "\n") } })
4. 检查隐性缺失值
查看有问题的列的取值分布,确认'00'或双0没有被误处理:
# 查看CONFIGURATION列的取值分布 table(training_data_clean$CONFIGURATION) # 查看STR_RGN_NBR列的取值分布 table(training_data_clean$STR_RGN_NBR)
如果发现有空字符串这类隐性缺失,可以用dplyr::na_if()将其转为NA后再处理:
training_data_clean <- training_data_clean %>% mutate(CONFIGURATION = na_if(CONFIGURATION, ""), STR_RGN_NBR = na_if(STR_RGN_NBR, "")) %>% na.omit()
内容的提问来源于stack exchange,提问作者Jaskeil

