如何在`mutate`里面的`map`中取消引用(!!)

问题描述 投票:4回答:2

我正在使用foomap2修改mutate中的嵌套数据框,我想根据foo$name在每个嵌套数据框中命名一个变量。我不确定nse / tidyeval unquotation的正确语法是什么。我的尝试:

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

foo[1,2] %>% unnest %>% names %>% .[11] == "one"
r dplyr purrr rlang tidyeval
2个回答
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

您可以在问题#541找到有关GitHub的更多详细信息: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"))

3
投票

这是因为不引用的时机。嵌套整齐的eval函数可能有点棘手,因为它是处理unquoting运算符的第一个整齐的eval函数。

我们改写一下:

mutate(data = map2(data, name, ~ mutate(.x, !!.y := "anything")))

mutate(data = map2(data, name, function(x, y) mutate(x, !!y := "anything")))

xy绑定仅在map2()调用函数时创建。因此,当第一个mutate()运行时,这些绑定尚不存在,并且您得到一个未找到对象的错误。有了公式,它有点难以看到,但公式扩展到一个函数采取.x.y论点,所以我们有同样的问题。

通常,最好避免在代码中使用复杂的嵌套逻辑,因为它会使读取更加困难。整齐的eval更加复杂,所以最好分步进行。作为一个额外的好处,在步骤中做事需要创建中间变量,如果命名良好,有助于理解函数正在做什么。

© www.soinside.com 2019 - 2024. All rights reserved.