如何用dplyr的mutate和across在R中实现多列对应乘积?
解决dplyr中mutate+across计算关联列乘积的报错问题
需求说明
现有两个数据框dft0和dft1,二者共享id列用于匹配观测;dft0中的列(如x/y/z)对应dft1中前缀为b_的列(如b_x/b_y/b_z)。需要用dplyr的mutate和across函数,计算每对对应列的乘积,生成名为p_列名的新列。
示例数据
library(dplyr) dft0 <- data.frame(id = 101:103, x = 1:3, y = 4:6, z = 7:9) dft1 <- data.frame(id = 101:103, b_x = 10:12, b_y = 13:15, b_z = 16:18)
报错代码及信息
尝试的代码:
vs <- c('x', 'y', 'z') dfts <- full_join(dft0, dft1, by = c('id')) %>% mutate(., across(vs, .fn = ~ .x * get(paste0('b_', .x)), .names = 'p_{.col}'))
报错信息:
Error in `mutate_cols()`: ! Problem with `mutate()` input `..1`. i `..1 = across(...)`. x first argument has length > 1 Caused by error in `get()`: ! first argument has length > 1 Run `rlang::last_error()` to see where the error occurred.
报错原因
报错核心是across的函数中,.x指代的是当前列的数值向量,而非列名。用paste0('b_', .x)会把列的每个数值都拼上b_,生成一个长度大于1的向量,而get()只能接受单个字符串作为参数,因此触发错误。
修正方案
需要获取当前遍历的列名而非列值,这里可以用cur_column()函数来获取当前列的名称,再拼接对应关联列的名称:
方案一:使用cur_column() + get()
vs <- c('x', 'y', 'z') dfts <- full_join(dft0, dft1, by = c('id')) %>% mutate(across(vs, ~ .x * get(paste0('b_', cur_column())), .names = 'p_{.col}'))
方案二:使用cur_column() + .data代词(更推荐,可读性更强)
vs <- c('x', 'y', 'z') dfts <- full_join(dft0, dft1, by = c('id')) %>% mutate(across(vs, ~ .x * .data[[paste0('b_', cur_column())]], .names = 'p_{.col}'))
运行结果
执行修正后的代码后,dfts会新增p_x/p_y/p_z三列,对应每对列的乘积:
> dfts id x y z b_x b_y b_z p_x p_y p_z 1 101 1 4 7 10 13 16 10 52 112 2 102 2 5 8 11 14 17 22 70 136 3 103 3 6 9 12 15 18 36 90 162
内容的提问来源于stack exchange,提问作者DOS
相关产品推荐
相关产品推荐

