r - 使用 dplyr::case_when 进行整洁的评估编程

标签 r dplyr lazy-evaluation nse

我尝试编写一个围绕 dplyr::case_when() 函数的简单函数。我阅读了 https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html 上的 programming with dplyr 文档但无法弄清楚这如何与 case_when() 函数一起使用。

我有以下数据:

data <- tibble(
   item_name = c("apple", "bmw", "bmw")
)

以及以下列表:

cat <- list(
   item_name == "apple" ~ "fruit",
   item_name == "bmw" ~ "car"
)

然后我想写一个这样的函数:

category_fn <- function(df, ...){
   cat1 <- quos(...)
   df %>%
     mutate(category = case_when((!!!cat1)))
}

不幸的是,category_fn(data,cat) 在这种情况下给出了评估错误。我想获得与通过以下方式获得的输出相同的输出:

data %>% 
   mutate(category = case_when(item_name == "apple" ~ "fruit",
                               item_name == "bmw" ~ "car"))

有什么方法可以做到这一点?

最佳答案

1) pass list 使用wrapper包中的let以及问题中的datacat无需以任何方式修改输入。

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

给予:

# A tibble: 3 x 2
  item_name category
      <chr>    <chr>
1     apple    fruit
2       bmw      car
3       bmw      car

1a) 使用问题中的 tidyeval/rlang 和 datacat:

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)

给出与上面相同的结果。

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

给予:

# A tibble: 3 x 2
  item_name category
      <chr>    <chr>
1     apple    fruit
2       bmw      car
3       bmw      car

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

关于r - 使用 dplyr::case_when 进行整洁的评估编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48023142/

相关文章:

返回一组列中的第二大值

c++ - RAII : Initializing data member in const method

r - 转为 base58 的十六进制字符串

r - 如何按每 7 行分组,并按中位数聚合这 7 个值?

r - 如果列不同,则用字符串分隔列

java - 具有惰性评估的复杂结构翻译

scala - 在迭代器列表上延迟这个 flatMap

r - 查找常见和唯一的数字并将它们放入 R 中的新整数向量中

r - 如何四舍五入到最接近的 10(或 100 或 X)?

r - 使用条件变异分配多个值