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

如何将多值列独热编码逻辑转为tidymodels的recipe步骤?

在tidymodels中实现多值列的拆分与独热编码

问题场景

已有如下R数据框:

library(tidyverse)
# 示例数据框
df <- data.frame(
  id = 1:3,
  fruits = c("apple | oranges", "apple | bananas", "bananas | oranges")
)

对应表格:

idfruits
1apple
2apple
3bananas

已经通过tidyverse代码实现fruits列的拆分与独热编码:

# 步骤1:按|拆分多行
df_separated <- df %>%
  separate_rows(fruits, sep = " \\| ")

# 步骤2:生成哑变量
df_dummy <- df_separated %>%
  mutate(value = TRUE) %>%
  spread(fruits, value, fill = FALSE)

得到结果:

idapplebananasoranges
1TRUEFALSETRUE
2TRUETRUEFALSE
3FALSETRUETRUE

需要将该逻辑整合进tidymodels工作流,作为recipe步骤。


解决方案

方案1:借助textrecipes包快速实现

如果安装了textrecipes包,可以用现成的步骤处理多值列:

library(tidymodels)
library(textrecipes)

# 创建并预处理recipe
fruit_recipe <- recipe(~ id + fruits, data = df) %>%
  # 把字符串按" | "拆成列表列
  step_mutate(fruits_list = str_split(fruits, " \\| ")) %>%
  # 对列表列做多值哑变量编码
  step_dummy_multi(fruits_list) %>%
  # 移除原列和中间列表列(可选)
  step_rm(fruits, fruits_list) %>%
  prep()

# 生成结果
bake(fruit_recipe, new_data = NULL)

方案2:自定义recipe步骤(无额外依赖)

如果不想依赖第三方包,可以自定义步骤完全复刻原tidyverse逻辑:

library(tidymodels)

# 1. 定义自定义步骤的框架
step_multi_dummy <- function(recipe, ..., role = "predictor", trained = FALSE, columns = NULL, sep = " \\| ", skip = FALSE, id = rand_id("multi_dummy")) {
  add_step(
    recipe,
    step_multi_dummy_new(
      terms = enquos(...),
      role = role,
      trained = trained,
      columns = columns,
      sep = sep,
      skip = skip,
      id = id
    )
  )
}

step_multi_dummy_new <- function(terms, role, trained, columns, sep, skip, id) {
  step(
    subclass = "multi_dummy",
    terms = terms,
    role = role,
    trained = trained,
    columns = columns,
    sep = sep,
    skip = skip,
    id = id
  )
}

# 2. 实现训练阶段逻辑(提取所有类别)
prep.step_multi_dummy <- function(x, training, info = NULL, ...) {
  col_names <- recipes::terms_select(x$terms, info = info)
  
  # 从训练数据中提取所有可能的类别
  all_categories <- training %>%
    separate_rows(all_of(col_names), sep = x$sep) %>%
    pull(all_of(col_names)) %>%
    unique() %>%
    sort()
  
  step_multi_dummy_new(
    terms = x$terms,
    role = x$role,
    trained = TRUE,
    columns = list(col = col_names, categories = all_categories, sep = x$sep),
    sep = x$sep,
    skip = x$skip,
    id = x$id
  )
}

# 3. 实现应用阶段逻辑(生成哑变量)
bake.step_multi_dummy <- function(object, new_data, ...) {
  col_name <- object$columns$col
  categories <- object$columns$categories
  sep <- object$columns$sep
  
  new_data %>%
    separate_rows(all_of(col_name), sep = sep) %>%
    mutate(value = TRUE) %>%
    spread(all_of(col_name), value, fill = FALSE) %>%
    group_by(id) %>% # 这里假设id是分组主键,根据实际数据调整
    summarise(across(all_of(categories), ~any(.x)), .groups = "drop") %>%
    right_join(new_data %>% select(-all_of(col_name)), by = "id") %>%
    select(id, all_of(categories), everything())
}

# 4. 使用自定义步骤创建recipe
fruit_recipe <- recipe(~ id + fruits, data = df) %>%
  step_multi_dummy(fruits, sep = " \\| ") %>%
  prep()

# 生成结果
bake(fruit_recipe, new_data = NULL)

验证结果

两种方案都能输出和原tidyverse代码一致的结果:

idapplebananasoranges
1TRUEFALSETRUE
2TRUETRUEFALSE
3FALSETRUETRUE

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:44:58