аккуратная оценка в тидыре - PullRequest
1 голос
/ 11 января 2020

Это вопрос о кодах в vignette("in-packages")

Набор данных находится ниже.

(mini_iris <- iris %>% 
    as_tibble() %>% 
    .[c(1, 2, 51, 52, 101, 102), ])
#> # A tibble: 6 x 5
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species   
#>          <dbl>       <dbl>        <dbl>       <dbl> <fct>     
#> 1          5.1         3.5          1.4         0.2 setosa    
#> 2          4.9         3            1.4         0.2 setosa    
#> 3          7           3.2          4.7         1.4 versicolor
#> 4          6.4         3.2          4.5         1.5 versicolor
#> 5          6.3         3.3          6           2.5 virginica 
#> 6          5.8         2.7          5.1         1.9 virginica

Если имена столбцов находятся в символьном векторе (возможно, из вызова функции) , вы можете предоставить это one_of ()

nest_egg <- function(data, cols) {
  nest(data, egg = one_of(cols))
}

nest_egg(mini_iris, c("Petal.Length", "Petal.Width", "Sepal.Length", "Sepal.Width"))
#> # A tibble: 3 x 2
#>   Species               egg
#>   <fct>      <list<df[,4]>>
#> 1 setosa            [2 × 4]
#> 2 versicolor        [2 × 4]
#> 3 virginica         [2 × 4]

И затем, виньетка описывает, что

Использование one_of() здесь важно; если вы не используете его, а данные содержат столбец с именем cols, nest() вложит его вместо столбцов, названных в cols.

Я думаю, что это можно решить с помощью аккуратная оценка .

library(rlang)
nest_egg2 <- function(data, cols) {
  cols <- enexprs(cols)
  nest(data, egg = !!!cols)
}
nest_egg2(mini_iris, c("Petal.Length", "Petal.Width", "Sepal.Length", "Sepal.Width"))

но она показывает ошибку

Error: `!!!` can't be supplied with a name. Only the operand's names are retained.

В следующем разделе Vignette описывает, что

Чтобы обеспечить работающий интерфейс как и функция tidyr, которую вы переносите, вы должны передать аргумент, используя {{arg}}. {{}} - это специальный оператор tidy eval, который захватывает выражение, предоставленное пользователем, и перенаправляет его в другую функцию, поддерживающую tidy eval.

nest_egg <- function(df, cols) {
  nest(df, egg = {{ cols }})
}

nest_egg(mini_iris, -Species)

Но мне интересно, что у моего nest_egg2 проблема в

Ответы [ 2 ]

1 голос
/ 13 января 2020

В контексте выбора (не в контексте действия, как в mutate()), вы можете использовать !!! внутри c(), если вам нужно дать имя:

nest_egg <- function(df, cols) {
  nest(df, egg = c(!!!cols))
}

Так как tidyselect также поддерживает векторы имен, вы также можете просто заключить его в кавычки, оба подхода верны:

nest_egg <- function(df, cols) {
  nest(df, egg = !!cols)
}

Отмена кавычек гарантирует, что env-переменная cols выбрана над переменной данных cols, для случая, когда df имеет столбец с именем `cols.

Но на самом деле правильный подход в контексте выбора - просто использовать one_of() (или all_of() в следующей версии).

0 голосов
/ 11 января 2020

Итак, здесь есть две вещи:

  1. Функция nest принимает вектор, однако enexprs возвращает список
  2. Вам не нужно (bang bang / eval) для гнезда. В основном требуется оценка, если функция вызывает имя столбца без кавычек "", однако в вашем случае, поскольку cols уже является вектором строки, он будет работать без оценки.

Так что это должно работа;

library(dplyr)
library(tidyr)

mini_iris <- 
  iris %>% 
  as_tibble() %>% 
  .[c(1, 2, 51, 52, 101, 102), ]

nest_egg2 <- function(data, cols) {
  nest(data, egg = cols)
}

nest_egg2(mini_iris, c("Petal.Length", "Petal.Width", "Sepal.Length", "Sepal.Width"))

# # A tibble: 3 x 2
# Species               egg
# <fct>      <list<df[,4]>>
# setosa            [2 x 4]
# versicolor        [2 x 4]
# virginica         [2 x 4]
...