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

如何用match.fun动态构建含parsnip模型调用的tibble?

动态生成Parsnip模型调用列的问题

现有数据结构

现有如下结构的tibble:

regression_to_parsnip_call_tbl <- tibble::tibble(
  engine = c(
    "lm",
    "brulee",
    "gee",
    "glm",
    "glmer",
    "glmnet",
    "gls",
    "h2o",
    "keras",
    "lme",
    "lmer",
    "spark",
    "stan",
    "stan_glmer"
  ),
  mode = "regression"
)

需求

需要为该tibble新增一列,存储形如linear_reg(mode = "regression", engine = "lm")的parsnip模型调用,且不希望硬编码目标函数,后续需支持cubist_rules等其他回归模型。

报错信息

尝试相关代码时出现如下报错:

Error in `dplyr::mutate()`:
! Problem while computing `model_spec = purrr::pmap(dplyr::cur_data(),
  match.fun(mt))`.
Caused by error in `get()`:
! object 'mt' of mode 'function' was not found
Run `rlang::last_error()` to see where the error occurred.

解决方案

核心思路是通过动态映射模型函数名,结合rlang的符号引用/解引用功能实现无硬编码的模型调用生成,同时用purrr处理逐行逻辑:

方法1:内嵌模型映射规则

先在原表中添加模型函数名的映射,再逐行生成模型对象:

library(dplyr)
library(purrr)
library(parsnip)
library(rlang)

regression_to_parsnip_call_tbl <- regression_to_parsnip_call_tbl %>%
  # 定义引擎与模型函数的映射,后续新增模型只需扩展此处
  mutate(model_fn = case_when(
    engine %in% c("lm", "brulee", "gee", "glm", "glmer", "glmnet", "gls", "h2o", "keras", "lme", "lmer", "spark", "stan", "stan_glmer") ~ "linear_reg",
    engine == "cubist" ~ "cubist_rules",
    # 可继续添加更多模型映射
    TRUE ~ NA_character_
  )) %>%
  # 动态调用模型函数生成调用对象
  mutate(model_spec = pmap(list(mode, engine, model_fn), 
                          function(mode_val, engine_val, fn_name) {
                            # 将字符串函数名转为符号,再解引用调用
                            fn_sym <- sym(fn_name)
                            eval_tidy(expr(!!fn_sym(mode = !!mode_val, engine = !!engine_val)))
                          }))

方法2:独立映射表实现灵活扩展

如果需要更清晰的管理逻辑,可以单独定义模型-引擎映射表,再关联生成:

# 独立定义模型-引擎映射表,后续新增模型/引擎只需修改此表
model_engine_map <- tibble::tibble(
  engine = c(
    "lm", "brulee", "gee", "glm", "glmer", "glmnet", "gls", "h2o", "keras", 
    "lme", "lmer", "spark", "stan", "stan_glmer", "cubist"
  ),
  model_fn = c(
    rep("linear_reg", 14),
    "cubist_rules"
  ),
  mode = "regression"
)

# 关联原表并生成模型调用
regression_to_parsnip_call_tbl <- regression_to_parsnip_call_tbl %>%
  left_join(model_engine_map, by = c("engine", "mode")) %>%
  mutate(model_spec = pmap(list(mode, engine, model_fn), 
                          function(mode_val, engine_val, fn_name) {
                            fn_sym <- sym(fn_name)
                            eval_tidy(expr(!!fn_sym(mode = !!mode_val, engine = !!engine_val)))
                          }))

关键说明

  • 用rlang::sym()将字符串形式的函数名转为符号,再通过!!解引用实现动态调用,彻底避免硬编码函数名
  • 模型与引擎的映射逻辑单独抽离,后续新增模型(如cubist_rules)只需扩展映射规则,无需修改核心生成代码
  • purrr::pmap()负责逐行传递参数,确保每个模型调用的mode和engine参数准确匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:45:34