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.