【问题标题】:How to pass an expression to the filter() verb the tidy way?如何以整洁的方式将表达式传递给 filter() 动词?
【发布时间】:2020-02-13 15:29:24
【问题描述】:

我有一种有效的方法,一种无效的方法,我无法弄清楚后者有什么问题。这里:

library(tidyverse)
get_these <- c(`Ideal E` = "cut == 'Ideal' & color == 'E'", 
               `Good J` = "cut == 'Good' & color == 'J'")

# This works:
get_these %>% 
  map(rlang::parse_expr) %>% 
  map(function(pick_these) 
    diamonds %>% 
      filter(!!pick_these)) %>% 
  tibble(goods = .) %>% 
  mutate(wat = names(get_these))

# This does not:
tibble(pick_these = get_these %>% 
         map(rlang::parse_expr)) %>% 
  mutate(wat = names(get_these), 
         goods = list(diamonds)) %>% 
  mutate(goods = pmap(.l = dplyr::select(., 
                                         goods, 
                                         pick_these), 
                      .f = function(goods, pick_these) {
                        goods %>% filter(!!pick_these)
                      })) %>% 
  dplyr::select(goods, wat)

【问题讨论】:

    标签: r tidyverse tidyeval


    【解决方案1】:

    我们可以select 感兴趣的列并提取具有..1..2(或.x.y - 如果只有 2 列)的组件

    library(dplyr)
    library(tibble)
    library(purrr)
    tibble(pick_these = get_these %>% 
             map(rlang::parse_expr)) %>% 
      mutate(wat = names(get_these), 
             goods = list(diamonds))  %>% 
             mutate(goods = pmap(select(., goods, pick_these), ~ {
                                         ..1 %>% 
                                              filter(rlang::eval_tidy( ..2))
    
                                             })) %>%
                                              dplyr::select(goods, wat)
    
    # A tibble: 2 x 2
    #  goods                 wat    
    #  <list>                <chr>  
    #1 <tibble [3,903 × 10]> Ideal E
    #2 <tibble [307 × 10]>   Good J 
    

    【讨论】:

      【解决方案2】:

      实际上,这是可行的:

      tibble(pick_these = get_these %>% 
               map(rlang::parse_expr)) %>% 
        mutate(wat = names(get_these), 
               goods = list(diamonds)) %>% 
        mutate(goods = pmap(.l = dplyr::select(., 
                                               goods, 
                                               pick_these), 
                            .f = function(goods, pick_these) {
                              goods %>% filter(rlang::eval_tidy(pick_these))
                            })) %>% 
        dplyr::select(goods, wat)
      

      所以诀窍是使用rlang::eval_tidy() 而不是!!。在阅读@akrun 的答案之前我不知道,我仍然不知道为什么!! 在这种情况下不起作用。

      【讨论】:

      • !! 在上下文中评估其参数,而不是在数据框中。这就是它找不到pick_these的原因。
      • 抱歉,我现在看到pick_these 不仅是一个数据框字段,它还作为函数参数显式传递。那么它不起作用的原因是时间:!!mutate() 处理得太早了。有解决此问题的想法的未解决问题:github.com/r-lib/rlang/issues/845
      猜你喜欢
      • 1970-01-01
      • 2017-11-19
      • 1970-01-01
      • 2013-10-30
      • 2018-09-22
      • 2011-06-30
      • 1970-01-01
      • 2022-11-23
      • 2020-02-25
      相关资源
      最近更新 更多