3

我很抱歉造成混乱,但最终,我发布的第一个示例(在页面底部)并没有帮助我弄清楚 tidyeval 如何与 mutate 一起工作,所以我添加了一个新示例。

我想创建一个需要三个参数的函数:

  • 一个数据框
  • 要变异的列
  • 一个变量(来自数据框)来替换正在变异的值

例如,用我尝试过mpg的值替换其中的值:carb

I tried this
colToX <- function(dt, ..., repl) {
  cols <- quos(...)
  repl <- quo(repl)
  mutate_at(dt, vars(!!!cols), funs(function(x) !!repl))
}

colToX(mtcars, mpg, repl = carb)

这不起作用,因为:

mutate_impl(.data, dots) 中的错误:列mpg的类型函数不受支持

我的第一个例子(@MrFlick 和 @UseR 都适用于此):

例如,下面的应该mutate()将所有 1 分配给传入的变量...

colTo1 <- function(dt, ...) {
col <- quo(...)
mutate(mtcars, !!col := 1)
}

colTo1(mtcars, mpg)

错误:LHS 必须是名称或字符串

最终,输出应该与mutate(mtcars, mpg = 1)

4

2 回答 2

4

@MrFlick 的解决方案适用于单列情况,但由于 OP 用作...参数,我假设 OP 还希望函数能够接收多列。例如,以下内容将不起作用:

colTo1 <- function(dt, ...) {
  col <- quo_name(quo(...))
  mutate(dt, !!col := 1)
}

colTo1(mtcars, mpg, cyl)

继承错误(x,“quosure”):找不到对象“cyl”

我们可以做的是使用quos代替quomutate_at代替mutate

colTo1 <- function(dt, ...) {
  cols <- quos(...)
  mutate_at(dt, vars(!!!cols), function(x) x=1)
}

quos将每个参数 from...转换为 quosures 向量。使用mutate_atvars语法和与!!!from的显式拼接rlang,我们可以取消引用 中的每个 quosure cols,并在那些指定的列上进行变异。

现在这按预期工作:

colTo1(mtcars, mpg, cyl)

结果:

   mpg cyl  disp  hp drat    wt  qsec vs am gear carb
1    1   1 160.0 110 3.90 2.620 16.46  0  1    4    4
2    1   1 160.0 110 3.90 2.875 17.02  0  1    4    4
3    1   1 108.0  93 3.85 2.320 18.61  1  1    4    1
4    1   1 258.0 110 3.08 3.215 19.44  1  0    3    1
5    1   1 360.0 175 3.15 3.440 17.02  0  0    3    2
6    1   1 225.0 105 2.76 3.460 20.22  1  0    3    1
7    1   1 360.0 245 3.21 3.570 15.84  0  0    3    4
8    1   1 146.7  62 3.69 3.190 20.00  1  0    4    2
9    1   1 140.8  95 3.92 3.150 22.90  1  0    4    2
10   1   1 167.6 123 3.92 3.440 18.30  1  0    4    4
...

1让 " " 成为传递给函数的另一个参数也很容易:

colToX <- function(dt, ..., X) {
  cols <- quos(...)
  mutate_at(dt, vars(!!!cols), function(x) x=X)
}

colToX(mtcars, mpg, cyl, X = 2)

编辑: OP 将问题更改为要求它X应该是同一数据框中的另一列。以下是我的新解决方案:

colToX <- function(dt, ..., X) {
  cols <- quos(...)
  X_quo <- enquo(X)
  mutate_at(dt, vars(!!!cols), funs(.data$`!!`(X_quo)))
}

colToX(mtcars, mpg, cyl, X = hp)

在这里,我使用该funs函数创建对从vars. .data指的是输入数据帧mutate_at(在这种情况下dt)。我曾经enquo将所谓的 fromX转换为 quosure 并使用!!.

结果:

   mpg cyl  disp  hp drat    wt  qsec vs am gear carb
1  110 110 160.0 110 3.90 2.620 16.46  0  1    4    4
2  110 110 160.0 110 3.90 2.875 17.02  0  1    4    4
3   93  93 108.0  93 3.85 2.320 18.61  1  1    4    1
4  110 110 258.0 110 3.08 3.215 19.44  1  0    3    1
5  175 175 360.0 175 3.15 3.440 17.02  0  0    3    2
6  105 105 225.0 105 2.76 3.460 20.22  1  0    3    1
7  245 245 360.0 245 3.21 3.570 15.84  0  0    3    4
8   62  62 146.7  62 3.69 3.190 20.00  1  0    4    2
9   95  95 140.8  95 3.92 3.150 22.90  1  0    4    2
10 123 123 167.6 123 3.92 3.440 18.30  1  0    4    4
...
于 2018-02-20T19:03:20.023 回答
2

正如错误所说“错误:LHS 必须是名称或字符串”,其中 LHS 表示左侧,它专门指的是该!!col := 1部分。您需要将您所做的 quosure 转换为字符串或符号。获得 quosure 的字符串版本可能是最简单的quo_name

colTo1 <- function(dt, ...) {
    col <- quo_name(quo(...))
    mutate(mtcars, !!col := 1)
}
于 2018-02-20T18:20:12.920 回答