如何在列上使用tidyeval进行变异?

时间:2018-02-20 17:32:41

标签: r dplyr tidyeval

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

我想创建一个带三个args的函数:

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

例如,要使用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&#39; s和@ UseR&#39; s都可以正常工作):

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

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

colTo1(mtcars, mpg)
  

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

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

相同

2 个答案:

答案 0 :(得分:4)

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

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

colTo1(mtcars, mpg, cyl)
  

继承错误(x,&#34; quosure&#34;):object&#39; cyl&#39;找不到

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

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

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

现在这可以按预期工作:

cols

<强>结果:

colTo1(mtcars, mpg, cyl)

它也很容易让#34; 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 ... &#34;是另一个传递给函数的参数:

1

修改:OP将问题更改为要求colToX <- function(dt, ..., X) { cols <- quos(...) mutate_at(dt, vars(!!!cols), function(x) x=X) } colToX(mtcars, mpg, cyl, X = 2) 应该是同一数据框中的另一列。以下是我的新解决方案:

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调用的内容转换为quosure,并使用X取消引用它。

<强>结果:

!!

答案 1 :(得分:2)

由于错误显示“错误:LHS必须是名称或字符串”,其中LHS表示左侧,它特别指的是!!col := 1部分。您需要将您制作的quosure转换为字符串或符号。使用quo_name

获取quosure的字符串版本可能最容易
colTo1 <- function(dt, ...) {
    col <- quo_name(quo(...))
    mutate(mtcars, !!col := 1)
}