Search code examples
rtidyversetidyeval

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


I have a way that works and one that does not, and I cannot figure out what's wrong with the latter. Here:

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)

Solution

  • We can select the columns of interest and extract the components with ..1, ..2 (or .x, .y - if there are only 2 columns)

    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