Tidyeval 评估 case_when
Tidyeval evaluate case_when
与 and 有点相关,我想创建字符串(使用闪亮的应用程序)稍后在 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")
}
然后为动态案例数重复字符串
mega_string <- map_chr(1:number_of_categories, ~ my_string(.x))
待办事项:
这是我无法完全拼凑的部分:使用这些字符串作为 case_when
中的参数。
# evaluate somehow?
iris %>%
mutate(
new_column = case_when(
# tidyeval mega_string?
paste(mega_string, collapse = "," )
)
)
这是正确的方法吗?您还能如何解决这个问题 - 非常感谢任何高级别或其他方面的帮助!
我们可以创建一个表达式并求值
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
#...
谢谢你的问答。
我在相同的上下文中使用(闪亮)。
我想提一下另一种更适合我的需要的方法,而且我发现它更容易理解逻辑:与其在要评估的字符串中传递变量,不如直接传递即将到来的字符串中的值来自 tibble 和 str_glue_data
mega <- tribble(
~min, ~max, ~size,
7, 8, "Big",
5, 6.9, "Medium",
4.9, 4, "Small"
) %>%
str_glue_data("Sepal.Length >= {min} & Sepal.Length <= {max} ~ '{size}'")
iris %>%
mutate(new_column = case_when(!!! map(mega, rlang::parse_expr)))
与 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")
}
然后为动态案例数重复字符串
mega_string <- map_chr(1:number_of_categories, ~ my_string(.x))
待办事项:
这是我无法完全拼凑的部分:使用这些字符串作为 case_when
中的参数。
# evaluate somehow?
iris %>%
mutate(
new_column = case_when(
# tidyeval mega_string?
paste(mega_string, collapse = "," )
)
)
这是正确的方法吗?您还能如何解决这个问题 - 非常感谢任何高级别或其他方面的帮助!
我们可以创建一个表达式并求值
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
#...
谢谢你的问答。 我在相同的上下文中使用(闪亮)。
我想提一下另一种更适合我的需要的方法,而且我发现它更容易理解逻辑:与其在要评估的字符串中传递变量,不如直接传递即将到来的字符串中的值来自 tibble 和 str_glue_data
mega <- tribble(
~min, ~max, ~size,
7, 8, "Big",
5, 6.9, "Medium",
4.9, 4, "Small"
) %>%
str_glue_data("Sepal.Length >= {min} & Sepal.Length <= {max} ~ '{size}'")
iris %>%
mutate(new_column = case_when(!!! map(mega, rlang::parse_expr)))