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

基于Base R将带引号函数参数传递至另一函数的...参数

用Base R解决裸变量传递到split_group函数的问题

问题背景

需要将geom_col_wrap函数group参数中的裸变量(如c(vs, am))传递给split_group函数,但直接传递会触发列不存在的错误——因为split_group依赖substitute(...)处理参数,却无法解析group这个中间变量。

原函数代码

geom_col_wrap函数

# 为便于阅读,删除了函数的其余部分
geom_col_wrap = function(data, mapping, group, ...) {
  data |> 
    split_group(group) 
}

split_group函数

# 该函数基于tidytable包实现
split_group = function(data, ...) {
  by_quote = as.list(substitute(...()))
  by = sapply(by_quote, deparse)

  split = vctrs::vec_split(data, data[c(by)])
  out = split[["val"]]
  names = do.call(paste, c(split[["key"]], sep = "_"))
  names(out) = names

  return(out)
}

错误重现

调用geom_col_wrap传入裸变量组时会报错:

geom_col_wrap(
  mtcars,
  mapping = ggplot2::aes(x = cyl, y = hp, color = am),
  group = c(vs, am)
)

错误信息:

Error in `[.data.frame`(data, c(by)) : undefined columns selected

错误根源是split_group中的as.list(substitute(...()))将传入的group直接解析为字符串"group",而非其实际对应的c(vs, am),导致无法匹配数据框列名。

Base R解决方案

通过捕获参数表达式并解析变量名的方式解决,无需依赖rlang或...参数:

修改后的geom_col_wrap函数

geom_col_wrap = function(data, mapping, group, ...) {
  # 捕获group参数的原始表达式
  group_expr = substitute(group)
  data |> 
    split_group(group_expr) 
}

修改后的split_group函数

split_group = function(data, group_expr) {
  # 解析表达式,提取内部变量符号
  by_quote = as.list(group_expr)[-1] # 移除c()调用,保留变量列表
  by = sapply(by_quote, deparse) # 将符号转为列名字符串

  split = vctrs::vec_split(data, data[c(by)])
  out = split[["val"]]
  names = do.call(paste, c(split[["key"]], sep = "_"))
  names(out) = names

  return(out)
}

验证调用

修改后重新执行调用即可正常返回分组结果:

result = geom_col_wrap(
  mtcars,
  mapping = ggplot2::aes(x = cyl, y = hp, color = am),
  group = c(vs, am)
)
str(result) # 查看按vs和am分组后的列表结构

核心原理

  1. 在geom_col_wrap中用substitute(group)捕获用户传入的原始表达式(而非变量值),确保传递给split_group的是c(vs, am)而非字符串"group"。
  2. 在split_group中解析传入的表达式:通过as.list(group_expr)[-1]剥离c()函数调用,提取内部的变量符号,再用deparse将符号转换为可用于索引数据框的列名字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:05:37