как заключить в кавычки (!!) внутри `map` внутри` mutate` - PullRequest
5 голосов
/ 10 апреля 2019

Я изменяю вложенные фреймы данных внутри foo с помощью map2 и mutate, и я хотел бы назвать переменную в каждом вложенном фрейме данных в соответствии с 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:

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

Ответы [ 2 ]

5 голосов
/ 10 апреля 2019

Похоже, что это функция / ошибка (не уверен, см. Ниже связанную проблему GitHub) того, как !! работает в mutate и map. Решение состоит в том, чтобы определить пользовательскую функцию, в этом случае отмена кавычек работает как ожидалось.

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 () в ошибке dplyr :: mutate (), в то время как автономный вызов map2 () работает ; обратите внимание, что проблема была закрыта в сентябре 2018 года, поэтому я предполагаю, что это предполагаемое поведение.


Альтернативой может быть использование group_split вместо nest, и в этом случае мы избежать вопроса без цитирования

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

mtcars %>%
    group_split(gear) %>%
    map2(nms, ~.x %>% mutate(!!.y := "anything"))
3 голосов
/ 10 апреля 2019

Это из-за времени отмены цитирования. Вложение аккуратных eval-функций может быть немного сложнее, потому что это самая первая аккуратная eval-функция, которая обрабатывает операторы без кавычек.

Давайте перепишем это:

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(), эти привязки еще не существуют, и вы получаете ошибку «объект не найден». С формулой это немного сложнее увидеть, но формула расширяется до функции, принимающей .x и .y аргументов, поэтому у нас та же проблема.

В целом, лучше избегать сложной вложенной логики в вашем коде, потому что это затрудняет чтение. С Tidy Eval это еще сложнее, поэтому лучше делать все по шагам. В качестве дополнительного бонуса, выполнение действий поэтапно требует создания промежуточных переменных, которые, при правильном названии, помогают понять, что делает функция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...