смешанное поведение purrr :: pmap с rlang;«цитировать» или не цитировать аргумент, который является Q - PullRequest
0 голосов
/ 22 мая 2018

У меня есть пользовательская функция, где я читаю введенные переменные из кадра данных, используя rlang.Эта функция прекрасно работает независимо от , независимо от того, указаны ли введенные аргументы в кавычках или без кавычек.Но, как ни странно, когда эта функция используется с purrr::pmap, она работает, только если аргумент заключен в кавычки.

Поэтому у меня два вопроса:

  1. Почемуповедение функции таким образом?

  2. Как я могу сделать функцию, используя rlang, чтобы мне не приходилось заключать аргументы в кавычки, даже если она используется в purrr::pmap?

Вот минимальное представление, использующее простую функцию для выделения этой проблемы:

# loading the needed libraries
library(rlang)
library(dplyr)
library(purrr)


# defining the function
tryfn <- function(data, x, y) {
  data <-
    dplyr::select(
      .data = data,
      x = !!rlang::enquo(x),
      y = !!rlang::enquo(y)
    )

  # creating a dataframe of means
  result_df <- data.frame(mean.x = mean(data$x), mean.y = mean(data$y))

  # return the dataframe
  return(result_df)
}

# without quotes (works!)
tryfn(iris, Sepal.Length, Sepal.Width)
#>     mean.x   mean.y
#> 1 5.843333 3.057333

# with quotes (works!)
tryfn(iris, "Sepal.Length", "Sepal.Width")
#>     mean.x   mean.y
#> 1 5.843333 3.057333

# pmap without quotes (doesn't work)
purrr::pmap(.l = list(
  data = list(iris, mtcars, ToothGrowth),
  x = list(Sepal.Length, wt, len),
  y = list(Sepal.Width, mpg, dose)
),
.f = tryfn)
#> Error in is.data.frame(.l): object 'Sepal.Length' not found

# pmap with quotes (works!)
purrr::pmap(.l = list(
  data = list(iris, mtcars, ToothGrowth),
  x = list("Sepal.Length", "wt", "len"),
  y = list("Sepal.Width", "mpg", "dose")
),
.f = tryfn)
#> [[1]]
#>     mean.x   mean.y
#> 1 5.843333 3.057333
#> 
#> [[2]]
#>    mean.x   mean.y
#> 1 3.21725 20.09062
#> 
#> [[3]]
#>     mean.x   mean.y
#> 1 18.81333 1.166667

Создано в 2018-05-21 пакетом представ. (v0.2.0).

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Проблема была в том, что R видел Sepal.Length, wt, len символов, поэтому он пытался посмотреть в текущей среде и оценить их.Конечно, это приводило к ошибкам, поскольку они были столбцами фрейма данных.Когда вы их цитировали, R не пытался вычислять и возвращал значения, поскольку он видел их как строки.

Если вы замените list на base::alist или dplyr::vars или rlang::exprs, это должно сработать

Примечание: поскольку мы уже цитируем входные данные, нам больше не нужно использовать rlang::enquo внутри tryfn.

# loading the needed libraries
library(rlang)
library(tidyverse)

# defining the function
tryfn <- function(data, x, y) {
  data <-
    dplyr::select(
      .data = data,
      x = !! x,
      y = !! y
    )

  # creating a data frame of means
  result_df <- data.frame(mean.x = mean(data$x), mean.y = mean(data$y))

  # return the data frame
  return(result_df)
}

# alist handles its arguments as if they described function arguments. 
# So the values are not evaluated, and tagged arguments with no value are 
# allowed whereas list simply ignores them. 

purrr::pmap(.l = list(
  data = list(iris, mtcars, ToothGrowth),
  x    = alist(Sepal.Length, wt, len),
  y    = alist(Sepal.Width, mpg, dose)
),
.f = tryfn)

#> [[1]]
#>     mean.x   mean.y
#> 1 5.843333 3.057333
#> 
#> [[2]]
#>    mean.x   mean.y
#> 1 3.21725 20.09062
#> 
#> [[3]]
#>     mean.x   mean.y
#> 1 18.81333 1.166667


purrr::pmap(.l = list(
  data = list(iris, mtcars, ToothGrowth),
  x    = dplyr::vars(Sepal.Length, wt, len),
  y    = dplyr::vars(Sepal.Width, mpg, dose)
),
.f = tryfn)

#> [[1]]
#>     mean.x   mean.y
#> 1 5.843333 3.057333
#> 
#> [[2]]
#>    mean.x   mean.y
#> 1 3.21725 20.09062
#> 
#> [[3]]
#>     mean.x   mean.y
#> 1 18.81333 1.166667

purrr::pmap(.l = list(
  data = list(iris, mtcars, ToothGrowth),
  x    = rlang::exprs(Sepal.Length, wt, len),
  y    = rlang::exprs(Sepal.Width, mpg, dose)
),
.f = tryfn)

#> [[1]]
#>     mean.x   mean.y
#> 1 5.843333 3.057333
#> 
#> [[2]]
#>    mean.x   mean.y
#> 1 3.21725 20.09062
#> 
#> [[3]]
#>     mean.x   mean.y
#> 1 18.81333 1.166667

Создано в 2018-05-21 с помощью пакета prepx (v0.2.0).

0 голосов
/ 22 мая 2018

Проблема не с purrr, правда.Такое же поведение можно наблюдать с:

list(Sepal.Length) # Error: object 'Sepal.Length' not found

Как я понимаю, вся магия с !!, enquo и т.п. доступна, когда вы передаете аргументы в функцию вы создали .Вот почему он работает, чтобы передать имена полей без кавычек непосредственно tryfn().

Но с pmap() вы помещаете имена полей (Sepal.Width, wt и т. Д.) В определение list, а list это не нравится - поэтому pmap даже не получает возможности передать вещи в tryfn, так как ваши list barfs по определению.

Передача имен ваших полей в виде строк работает просто отлично, так как list может вместить этот тип данных, итогда у pmap есть шанс отобразить их в tryfn().

Отзыв Хэдли о квазиквотации с dplyr может быть полезен для вас.

Ответить на вашВторой вопрос:

Как я могу сделать функцию, используя rlang, чтобы мне не приходилось заключать аргументы в кавычки, даже если она используется в purrr :: pmap?

Youможно обернуть имена полей с помощью quo(), чтобы избежать буквального цитирования их как строк, хотя я не уверен, что это значительное улучшение:

purrr::pmap(.l = list(
  data = list(iris, mtcars, ToothGrowth),
  x = list(quo(Sepal.Length), quo(wt), quo(len)),
  y = list(quo(Sepal.Width), quo(mpg), quo(dose))
),
.f = tryfn) %>% 
  bind_rows(., .id="dataset")

  dataset    mean.x    mean.y
1       1  5.843333  3.057333
2       2  3.217250 20.090625
3       3 18.813333  1.166667
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...