You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行initial_split()后,如何将目标变量从chr转为fct类型

解决tidymodels中last_fit因目标变量非因子报错的问题

问题

运行last_fit()时触发报错,提示分类模型的目标变量必须是因子类型。常规数据框可以直接转换变量类型,但不清楚如何处理initial_split()生成的split对象。

错误信息

x train/test split: preprocessor 1/1, model 1/1:
  Error in `check_outcome()`:
  ! For a classification model, the outcome should be a factor.
Warning message:
All models failed. Run `show_notes(.Last.tune.result)` for more information. 

Error in `check_outcome()`:
! For a classification model, the outcome should be a factor.

复现代码

library(tidyverse)
library(tidymodels)

# 建模数据
df <- read_csv("https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv") %>% 
  mutate(
    virg = case_when(
      variety == "Virginica" ~ 'yes',
      TRUE ~ 'No',
    )) %>% 
  select(-variety)

# 拆分数据
df_split <- initial_split(df, prop = .75, strata = virg)

# 示例:单独转换训练/测试集的变量类型
df_training <- df_split %>% training() %>% mutate(virg = as.factor(virg))
df_test <- df_split %>% testing() %>% mutate(virg = as.factor(virg))

# 随机森林模型
rf_model <- rand_forest() %>% 
  set_engine('randomForest') %>% 
  set_mode('classification')

# 触发报错的last_fit调用
df_last_fit <- rf_model %>% 
  last_fit(virg ~ sepal.length +
             sepal.width +
             petal.length +
             petal.width,
           split = df_split
  )

解决方案

方法1:拆分前转换目标变量(推荐)

在数据拆分前就把目标变量转为因子,这样split对象中的训练和测试集会自动继承因子类型,无需后续手动处理:

df <- read_csv("https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv") %>% 
  mutate(
    virg = case_when(
      variety == "Virginica" ~ 'yes',
      TRUE ~ 'No',
    ) %>% as.factor() # 直接转换为因子
  ) %>% 
  select(-variety)

# 正常拆分数据
df_split <- initial_split(df, prop = .75, strata = virg)

# 直接运行last_fit
df_last_fit <- rf_model %>% 
  last_fit(virg ~ sepal.length + sepal.width + petal.length + petal.width,
           split = df_split
  )

方法2:修改已拆分的rsplit对象

如果已经完成数据拆分,可提取训练/测试集转换类型后,重新构建split对象:

# 提取并转换训练、测试集的目标变量
train_data <- training(df_split) %>% mutate(virg = as.factor(virg))
test_data <- testing(df_split) %>% mutate(virg = as.factor(virg))

# 重新构建rsplit对象
df_split_fixed <- make_splits(list(train = train_data, test = test_data),
                              data = bind_rows(train_data, test_data))

# 使用修复后的split对象运行last_fit
df_last_fit <- rf_model %>% 
  last_fit(virg ~ sepal.length + sepal.width + petal.length + petal.width,
           split = df_split_fixed
  )

方法3:使用配方(Recipe)预处理(更符合tidymodels流程)

将变量类型转换作为预处理步骤整合到工作流中,这是tidymodels推荐的标准化流程:

# 创建配方,将字符型目标变量转为因子
iris_recipe <- recipe(virg ~ ., data = df) %>%
  step_string2factor(virg)

# 构建模型工作流
rf_workflow <- workflow() %>%
  add_recipe(iris_recipe) %>%
  add_model(rf_model)

# 运行last_fit
df_last_fit <- rf_workflow %>%
  last_fit(split = df_split)

内容的提问来源于stack exchange,提问作者user16329246

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:45:29