为何recipes::bake()会将字符型ID转为值全为NA的因子?
问题:recipes包bake()处理后ID列变为带训练集水平的因子且值全为NA
我有一个字符型ID,希望保留在数据中但不用于训练。查看经过bake()处理后的数据时,发现该ID列变为了包含所有取值水平的因子,但所有值均为NA。
复现代码
# 创建带唯一字符型ID的数据集 myData <- mtcars %>% mutate(myID = paste("j", row_number())) # 拆分数据集 myDataSplit <- initial_split(myData) # 查看测试集myID的类型:字符型 class(testing(myDataSplit)$myID) # [1] "character" # 将myID的角色从'predictor'改为'ID' myRecipe <- recipe(mpg ~., data = training(myDataSplit)) %>% update_role(myID, new_role="ID") # 预处理并应用到测试集 myTesting <- myRecipe %>% prep() %>% bake(testing(myDataSplit))
问题现象
此时myTesting中的myID变为因子且所有值均为NA:
> unique(myTesting$myID) [1] <NA> Levels: j1 j10 j13 j15 j16 j17 j19 j21 j22 j23 j24 j25 j26 j27 j28 j29 j3 j30 j32 j4 j5 j6 j7 j8
已尝试的无效方法
- 使用
step_factor2string(myID) - 创建recipe时设置
convert_strings = FALSE:
myRecipe <- recipe(mpg ~., data = training(myDataSplit), convert_strings = FALSE)
我正在使用workflow(),调用predict(myworflow, testing(myDataSplit))时它会自动执行bake操作,这似乎能正常工作,但bake()单独处理时的问题让我觉得自己遗漏了关键要点。
解决方法
问题核心在于:
bake()默认仅输出建模相关变量(预测变量、结果变量),ID角色的列不会被自动包含;- 即便ID列被意外包含,recipes默认会将字符型列转换为因子(基于训练集的水平),而测试集的ID值不在训练集水平范围内,因此被转为NA。
方法一:明确指定保留ID列并跳过预处理
通过step_skip()跳过对ID列的所有预处理,同时在bake()中明确指定要包含ID角色的列:
myRecipe <- recipe(mpg ~., data = training(myDataSplit)) %>% update_role(myID, new_role = "ID") %>% # 跳过对myID的预处理步骤 step_skip(myID) myTesting <- myRecipe %>% # 关闭字符型转因子的默认行为 prep(strings_as_factors = FALSE) %>% # 明确包含建模变量与ID列 bake(testing(myDataSplit), include = c(all_predictors(), all_outcomes(), all_roles("ID")))
方法二:配置ID角色的处理规则
使用update_role_requirements()设置ID列在训练阶段无需处理、在bake阶段需要保留,同时关闭字符转因子:
myRecipe <- recipe(mpg ~., data = training(myDataSplit)) %>% update_role(myID, new_role = "ID") %>% # 设置ID列:训练时不处理,bake时保留 update_role_requirements(role = "ID", bake = TRUE, train = FALSE) myTesting <- myRecipe %>% prep(strings_as_factors = FALSE) %>% bake(testing(myDataSplit))
补充说明
你使用workflow()的predict()时正常,是因为predict()默认仅返回预测结果,不会输出ID列,因此不会触发该问题。
内容的提问来源于stack exchange,提问作者paul79
相关产品推荐
相关产品推荐

