Tidyeval оценить case_when - PullRequest
       57

Tidyeval оценить case_when

1 голос
/ 05 мая 2020

В некоторой степени связано с аккуратным оценочным программированием с помощью dplyr :: case_when и Создание функции tidyeval внутри case_when , я хочу создавать строки (используя блестящее приложение) для последующего анализа внутри case_when функция. Вот пример:

library(tidyverse)

# simulated shiny inputs
new_column = sym("COL_NAME")

number_of_categories = 3

col1_text = "Big"
col1_min = 7.0
col1_max = 8.0

col2_text = "Medium"
col2_min = 5.0
col2_max = 6.9

col3_text = "Small"
col3_max = 4.9
col3_min = 4.0

columninput = sym("Sepal.Length")

ЖЕЛАТЕЛЬНЫЙ ВЫХОД

iris %>%
  mutate(new_column =
           case_when(
             !!columninput >= col1_min & !!columninput <= col1_max ~ col1_text,
             !!columninput  >= col2_min & !!columninput <= col2_max ~ col2_text,
             !!columninput  >= col3_min & !!columninput <= col3_max ~ col3_text
           )
  )

Поскольку единственное, что меняется между функциями, - это индекс, я подумал, что мы можем использовать общий шаблон для создания строки

# create single string
my_string <-function(i) {
  paste0("!!", columninput, " >= col", i, "_min & ", "!!", columninput, " <= col", i, "_max ~ col", i, "_text")
}

Затем повторите строку для динамики c количество случаев

mega_string <- map_chr(1:number_of_categories, ~ my_string(.x))

TODO:

Это часть, которую я не могу собрать вместе: использование этих строк в качестве аргументов в case_when.

# evaluate somehow?
iris %>%
  mutate(
    new_column = case_when(
      # tidyeval mega_string?
      paste(mega_string, collapse = "," )
      )
    )

Это вообще правильный подход? go Как еще вы могли бы *1026* решить эту проблему - любая помощь высокого уровня или иначе приветствуется!

1 Ответ

2 голосов
/ 05 мая 2020

Мы могли бы создать выражение и вычислить

library(dplyr)
library(stringr)
iris %>% 
   mutate(new_column = eval(rlang::parse_expr(str_c('case_when(', 
          str_c(mega_string, collapse=","), ')'))))
#    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species new_column
#1            5.1         3.5          1.4         0.2     setosa     Medium
#2            4.9         3.0          1.4         0.2     setosa      Small
#3            4.7         3.2          1.3         0.2     setosa      Small
#4            4.6         3.1          1.5         0.2     setosa      Small
#5            5.0         3.6          1.4         0.2     setosa     Medium
#6            5.4         3.9          1.7         0.4     setosa     Medium
#7            4.6         3.4          1.4         0.3     setosa      Small
#8            5.0         3.4          1.5         0.2     setosa     Medium
#9            4.4         2.9          1.4         0.2     setosa      Small
#10           4.9         3.1          1.5         0.1     setosa      Small
# ...

Или используя parse_expr с !!!

library(purrr)
iris %>%
   mutate(new_column = case_when(!!! map(mega_string, rlang::parse_expr)))
#    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species new_column
#1            5.1         3.5          1.4         0.2     setosa     Medium
#2            4.9         3.0          1.4         0.2     setosa      Small
#3            4.7         3.2          1.3         0.2     setosa      Small
#4            4.6         3.1          1.5         0.2     setosa      Small
#5            5.0         3.6          1.4         0.2     setosa     Medium
#6            5.4         3.9          1.7         0.4     setosa     Medium
#7            4.6         3.4          1.4         0.3     setosa      Small
#8            5.0         3.4          1.5         0.2     setosa     Medium
#...
...