如何以整洁的方式将表达式传递给 filter() 动词?

How to pass an expression to the filter() verb the tidy way?

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

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)

我们可以 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 

实际上,这有效:

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 的回答之前我不知道,我仍然不知道为什么 !! 在这种情况下不起作用。