mha*_*nga 13 r lazy-evaluation dplyr nse
我尝试编写一个包含dplyr :: case_when()函数的简单函数.我在https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html上阅读了dplyr文档的编程,但无法弄清楚它如何与case_when()函数一起工作.
我有以下数据:
data <- tibble(
item_name = c("apple", "bmw", "bmw")
)
Run Code Online (Sandbox Code Playgroud)
以下列表:
cat <- list(
item_name == "apple" ~ "fruit",
item_name == "bmw" ~ "car"
)
Run Code Online (Sandbox Code Playgroud)
然后我想写一个函数,如:
category_fn <- function(df, ...){
cat1 <- quos(...)
df %>%
mutate(category = case_when((!!!cat1)))
}
Run Code Online (Sandbox Code Playgroud)
不幸的是category_fn(data,cat),在这种情况下会给出评估错误 我想获得与通过以下方式获得的输出相同的输出:
data %>%
mutate(category = case_when(item_name == "apple" ~ "fruit",
item_name == "bmw" ~ "car"))
Run Code Online (Sandbox Code Playgroud)
这样做的方法是什么?
1)通列表使用let从wrapr包和data并cat从该工作没有以任何方式修改所述输入的问题.
library(dplyr)
library(wrapr)
category_fn <- function(data, List) {
let(c(CATEGORY = toString(sapply(List, format))),
data %>% mutate(category = case_when(CATEGORY)),
subsMethod = "stringsubs",
strict = FALSE)
}
category_fn(data, cat) # test
Run Code Online (Sandbox Code Playgroud)
赠送:
# A tibble: 3 x 2
item_name category
<chr> <chr>
1 apple fruit
2 bmw car
3 bmw car
Run Code Online (Sandbox Code Playgroud)
1a)中使用tidyeval/rlang和data和cat从所述的问题:
category_fn <- function(data, List) {
cat_ <- lapply(List, function(x) do.call("substitute", list(x)))
data %>% mutate(category = case_when(!!!cat_))
}
category_fn(data, cat)
Run Code Online (Sandbox Code Playgroud)
给出与上述相同的结果.
2)单独传递列表组件如果您打算单独传递每个组件cat而不是cat它自己,那么这可以工作:
category_fn <- function(data, ...) eval.parent(substitute({
data %>% mutate(category = case_when(...))
}))
category_fn(data, item_name == "apple" ~ "fruit",
item_name == "bmw" ~ "car") # test
Run Code Online (Sandbox Code Playgroud)
赠送:
# A tibble: 3 x 2
item_name category
<chr> <chr>
1 apple fruit
2 bmw car
3 bmw car
Run Code Online (Sandbox Code Playgroud)
2a)如果您更喜欢tidyeval/rlang,那么这种情况很简单:
library(dplyr)
library(rlang)
category_fn <- function(data, ...) {
cat_ <- quos(...)
data %>% mutate(category = case_when(!!!cat_))
}
category_fn(data, item_name == "apple" ~ "fruit",
item_name == "bmw" ~ "car") # test
Run Code Online (Sandbox Code Playgroud)
首先引用列表中的每个元素:
cat <- list(
quo(item_name == "apple" ~ "fruit"),
quo(item_name == "bmw" ~ "car")
)
Run Code Online (Sandbox Code Playgroud)
然后,您的函数不必引用cat对象本身.我还改变了使用"everything else"...参数来在调用中明确引用类别参数:
category_fn <- function(df, categories){
df %>%
mutate(category = case_when(!!!categories))
}
Run Code Online (Sandbox Code Playgroud)
然后函数的输出符合预期:
category_fn(data, cat)
# A tibble: 3 x 2
item_name category
<chr> <chr>
1 apple fruit
2 bmw car
3 bmw car
Run Code Online (Sandbox Code Playgroud)
为了完整起见,我注意到类别列表也适用于使用基本R quote()函数定义时的函数:
cat <- list(
quote(item_name == "apple" ~ "fruit"),
quote(item_name == "bmw" ~ "car")
)
> cat
[[1]]
item_name == "apple" ~ "fruit"
[[2]]
item_name == "bmw" ~ "car"
> category_fn(data, cat)
# A tibble: 3 x 2
item_name category
<chr> <chr>
1 apple fruit
2 bmw car
3 bmw car
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
822 次 |
| 最近记录: |