如何在`mutate`中的`map`中取消引号(!!)

时间:2019-04-10 05:19:02

标签: r dplyr purrr rlang tidyeval

我正在用foomap2来修改mutate内的嵌套数据框,我想根据{{1}在每个嵌套数据框中命名一个变量}。我不确定foo$name / nse取消引号的正确语法是什么。 我的尝试:

tidyeval

我希望嵌套数据框中的新创建变量的名称分别为“一个”,“两个”和“三个”。

如果我在普通library(tidyverse) foo <- mtcars %>% group_by(gear) %>% nest %>% mutate(name = c("one", "two", "three")) %>% mutate(data = map2(data, name, ~ mutate(.x, !!(.y) := "anything"))) #> Error in quos(...): object '.y' not found 上执行普通mutate,并且其中df是一个字符串,则我将基于普通语法进行尝试:

name

如果成功,则以下行应返回name <- "test" mtcars %>% mutate(!!name := "anything") # works fine

TRUE

2 个答案:

答案 0 :(得分:5)

这似乎是!!mutatemap中如何工作的功能/错误(不确定,请参阅下面的GitHub链接问题)。解决方案是定义一个自定义函数,在这种情况下,取消引用可以按预期工作。

library(tidyverse)

custom_mutate <- function(df, name, string = "anything")
    mutate(df, !!name := string)

foo <- mtcars %>%
  group_by(gear) %>%
  nest %>%
  mutate(name = c("one", "two", "three")) %>%
  mutate(data = map2(data, name, ~
      custom_mutate(.x, .y)))

foo[1,2] %>% unnest %>% names %>% .[11] == "one"
#[1] TRUE

您可以在GitHub的问题#541中找到更多详细信息:map2() call in dplyr::mutate() error while standalone map2() call works;请注意,此问题已于2018年9月结束,因此我认为这是预期的行为。


一种替代方法是使用group_split而不是nest,在这种情况下,  避免取消报价

nms <- c("one", "two", "three")

mtcars %>%
    group_split(gear) %>%
    map2(nms, ~.x %>% mutate(!!.y := "anything"))

答案 1 :(得分:3)

这是由于取消报价的时间。嵌套整齐的eval函数可能有点棘手,因为它是处理无引号运算符的第一个整齐的eval函数。

让我们重写一下:

"abc"

StringIndexOutOfBoundsException

mutate(data = map2(data, name, ~ mutate(.x, !!.y := "anything"))) mutate(data = map2(data, name, function(x, y) mutate(x, !!y := "anything"))) 绑定仅在x调用函数时创建。因此,当第一个y运行时,这些绑定尚不存在,并且会出现找不到对象的错误。使用公式很难看,但是公式扩展为带有map2()mutate()自变量的函数,因此我们有同样的问题。

通常,最好避免在代码中使用复杂的嵌套逻辑,因为这样会使代码难以阅读。有了整洁的评估,情况变得更加复杂,因此最好分步骤进行。作为额外的好处,分步执行操作需要创建中间变量,如果命名合理,则可以帮助您了解函数的功能。