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

在dplyr的mutate/across中使用字符串存储的变量名进行计算

问题

需要在dplyr::mutate()结合across()的计算中,使用字符串形式传入的列名作为乘数。尝试用{{col}}准引用失败,报错类型不匹配,目前可通过eval(parse())或get()实现,但想找到更贴合tidyverse风格的方法。

原错误代码

library(dplyr)
library(purrr)

vec_cols <- c('aa','bb')
 
atest <- data.frame(aa = 1:3,
                    bb = rep(0, 3),
                    cc = -(1:3),
                    dd = rep(10,3))
 
map(vec_cols, \(col) atest %>% 
  rowwise() %>%
  mutate(across(everything(), ~ {{col}} * .x)))

触发错误

Error in `map()`:
ℹ In index: 1.
Caused by error in `mutate()`:
ℹ In argument: `across(.cols = everything(), .fns = ~"aa" * .x)`.
ℹ In row 1.
Caused by error in `across()`:
! Can't compute column `aa`.
Caused by error in `"aa" * aa`:
! non-numeric argument to binary operator
Run `rlang::last_trace()` to see where the error occurred.
问题根源

{{col}}是tidyverse的准引用语法,仅适用于符号(symbol)类型的列名输入。当传入字符串时,{{col}}不会解析为对应列,而是直接保留字符串字面量,导致出现字符串与数值相乘的非法运算。

符合tidy风格的解决方案

1. 使用.data代词(推荐)

dplyr官方推荐用.data代词引用数据框列,支持字符串索引,完全符合tidy规范:

map(vec_cols, \(col) atest %>% 
      mutate(across(everything(), ~ .data[[col]] * .x)))

2. 字符串转符号后解引用

通过rlang::sym()将字符串转为符号,再用!!解引用,属于tidyverse元编程的标准用法:

map(vec_cols, \(col) atest %>% 
      mutate(across(everything(), ~ !!rlang::sym(col) * .x)))

额外优化:移除rowwise()

以上两种方案的计算都是向量化的,不需要rowwise()分组,移除后能显著提升运行效率。

输出结果

两种方案均能得到与eval(parse())/get()一致的结果:

[[1]]
  aa bb cc dd
1  1  0 -1 10
2  4  0 -4 20
3  9  0 -9 30

[[2]]
  aa bb cc dd
1  0  0  0  0
2  0  0  0  0
3  0  0  0  0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:04:54