R: Использование строки в качестве аргумента для изменения глагола в dplyr

Я создаю блестящее приложение, которое должно позволить пользователям определять новые переменные для построения графиков. В частности, я хочу разрешить пользователям определять выражение, которое будет использоваться в глаголе mutate. Сервер получает выражение в виде текста, и мне интересно, как заставить mutate выполнить его в dplyr 0.7. Я могу заставить его работать (частично), используя mutate_, но это устарело. Он также определяет имя нового столбца как полное выражение, а не как новую переменную

Вот воспроизводимый пример:

input_from_shiny <- "Petal.ratio = Petal.Length/Petal.Width"
iris_mutated <- iris %>% mutate_(input_from_shiny)

Это дает следующее

> head(iris_mutated)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Petal.ratio = Petal.Length/Petal.Width
1          5.1         3.5          1.4         0.2  setosa                                   7.00
2          4.9         3.0          1.4         0.2  setosa                                   7.00
3          4.7         3.2          1.3         0.2  setosa                                   6.50
4          4.6         3.1          1.5         0.2  setosa                                   7.50
5          5.0         3.6          1.4         0.2  setosa                                   7.00
6          5.4         3.9          1.7         0.4  setosa                                   4.25

Технически, я могу использовать регулярное выражение для извлечения нового имени переменной из строки и соответственно переименовать новый столбец, но мне интересно, как правильно реализовать его, используя последнюю версию dplyr (читал https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html, но не смог разобраться)

2 ответа

Решение

Мы можем использовать rlang::parse_quosure() вместе с !! (Bang Bang), чтобы получить тот же результат:

  • parse_quosure: анализирует предоставленную строку и преобразует ее в выражение

  • !!: удаляет кавычки, чтобы их можно было оценить tidyeval глаголы

Обратите внимание, что parse_quosure() был объявлен устаревшим и переименован в parse_quo() в rlang 0.2.0 согласно его документации. Если мы используем parse_quo()нам нужно указать среду для кавычек, например parse_quo(input_from_shiny, env = caller_env())

library(rlang)
library(tidyverse)

input_from_shiny <- "Petal.ratio = Petal.Length/Petal.Width"
iris_mutated <- iris %>% mutate_(input_from_shiny)

iris_mutated2 <- iris %>% 
  mutate(!!parse_quosure(input_from_shiny))
head(iris_mutated2)

#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa
#>   Petal.ratio = Petal.Length/Petal.Width
#> 1                                   7.00
#> 2                                   7.00
#> 3                                   6.50
#> 4                                   7.50
#> 5                                   7.00
#> 6                                   4.25


identical(iris_mutated, iris_mutated2)
#> [1] TRUE

Изменить: разделить LHS и RHS

lhs <- "Petal.ratio"
rhs <- "Petal.Length/Petal.Width"

iris_mutated3 <- iris %>% 
  mutate(!!lhs := !!parse_quosure(rhs))
head(iris_mutated3)

> head(iris_mutated3)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
  Petal.ratio
1        7.00
2        7.00
3        6.50
4        7.50
5        7.00
6        4.25

Создано в 2018-03-24 пакетом представлением (v0.2.0).

Пакет friendlyeval это упрощенный интерфейс к tidy eval, который пытается сделать вещи немного более понятными в подобных случаях.

Разделив вашу строку на две части, вы получите часть строки, которую вы хотите использовать в качестве имени столбца, и часть строки, которую вы хотите использовать в качестве выражения. Чтобы вы могли написать:

library(friendlyeval)
library(dplyr)
lhs <- "Petal.ratio"
rhs <- "Petal.Length/Petal.Width"

iris_mutated3 <- 
  iris %>% 
  mutate(!!treat_string_as_col(lhs) := !!treat_string_as_expr(rhs))
head(iris_mutated3)

Используя функцию на lhs, вы получаете проверку, что lhs может быть проанализирован как простое имя столбца.

friendlyeval код может быть преобразован в простой код eval в любое время с помощью надстройки RStudio.

Другие вопросы по тегам