mutate(across()) 与外部函数引用当前数据框中的其他变量而不传递第二个参数

mutate(across()) with external function that references other variables in current data frame without passing second argument

我想 mutate() 多个变量 across()

  1. 使用预先定义的函数
  2. 引用数据框中的其他变量但是
  3. 只需要一个参数(要改变的变量)和
  4. 不对函数内的那些变量的环境进行硬编码。

例如,此代码会将变量 x 添加到每个 yz:

library(dplyr)

# Data to modify
dtmp = tibble(x = 1:4, y = 10, z = 20)

# Function to pass to mutate(across())
addx = function(col, added){col + added}

# Any of these works
dtmp %>% mutate(across(c(y,z), addx, added=x))
dtmp %>% mutate(across(c(y,z), ~addx(.x, x)))
dtmp %>% mutate(across(c(y,z), function(var){addx(var, x)}))

通过在全局环境中对 dtmp$x 的引用进行硬编码,可以避免在 mutate(across()) 中向 addx 传递第二个参数:

addx = function(col){col + dtmp$x}
dtmp %>% mutate(across(c(y,z), addx))

但是,这个方案是有风险的。例如,如果数据框在 mutate 调用之前被分组(通过某个第 4 个变量),它将无法按预期运行,因为 dtmp$x 的长度与 [=16= 的子集的长度不同] 或 z 组内。

似乎应该可以编写 addx 这样我们就不必在 mutate(across()) 中向它传递第二个参数,也不必硬编码 dtmp$x 在函数定义中。这可能吗?换句话说,是否有一个 something(x) 可以使 addx() 定义中的 x 表达式在当前数据帧的环境中进行评估(如 mutate(across(data,...)) 中定义的那样) )?

解决方案的结构类似于

addx = function(col){col + Something(x)}
dtmp %>% mutate(across(c(y,z), addx))

示例用例:我们可能用来修改变量的一些函数可能会引用数据框中的许多其他变量,并且这些函数可能会在数据框中多次使用编码。写出来arg1=var1, arg2=var2, arg3=var3,...一团糟

您可以从 cur_data() 中提取 x 值,这在您对数据进行分组时也可以使用。

library(dplyr)

dtmp = tibble(x = 1:4, y = 10, z = 20)

# Function to pass to mutate(across())
addx = function(col) {col + cur_data()$x}

dtmp %>% mutate(across(c(y,z), addx))

#      x     y     z
#  <int> <dbl> <dbl>
#1     1    11    21
#2     2    12    22
#3     3    13    23
#4     4    14    24

如果您需要引用分组变量的函数,请改用cur_data_all()