Home > Software engineering >  Add list-column of tibbles to a tibble based on a list-column of filter quosures without helper func
Add list-column of tibbles to a tibble based on a list-column of filter quosures without helper func

Time:10-11

I have a list-column of filter quosures in a tibble, and I want to create another list-column of tibbles based on an existing tibble and the filter quosures:

library(tidyverse)

t1 <- tibble(x = letters)

tibble(filters = quos(x == "a", x == "b")) %>%
  mutate(dat = map(filters, ~filter(t1, !!.x)))
#> Error in local_error_context(dots = dots, .index = i, mask = mask): promise already under evaluation: recursive default argument reference or earlier problems?

This doesn't work as I expected, likely due to the interaction between map, !! and .x.

Using a helper function works as expected:

helper_function <- function(dat_in, filters_quo_in) {
  filter(dat_in, !!filters_quo_in)
}

tibble(filters = quos(x == "a", x == "b")) %>%
  mutate(dat = map(filters, ~helper_function(t1, .x)))
#> # A tibble: 2 × 2
#>   filters    dat             
#>   <quos>     <named list>    
#> 1 x == "a"   <tibble [1 × 1]>
#> 2 x == "b"   <tibble [1 × 1]>

Is there any way to get my first attempt to work in tidyverse without using a helper function? Or is there a better way to pass a list-column of filter-expressions to a tibble at the same time, and return the results as another list-column?

Created on 2022-10-11 with reprex v2.0.2

CodePudding user response:

According to this thread https://community.rstudio.com/t/when-and-how-to-use-and-x-y-pipe/101824/3

You're also currently trying to use the '.' to reference the data frame within the called function (after the ~) which won't work as you now have a different context - in a ~ function the '.' now refers to the first argument

This thread goes further. dplyr piping data - difference between `.` and `.x`

I found the answer in ?purrr::map

If a formula, e.g. ~ .x 2, it is converted to a function. There are three ways to refer to the arguments:

For a single argument function, use .

For a two argument function, use .x and .y

For more arguments, use ..1, ..2, ..3 etc

tibble(filters = quos(x == "a", x == "b")) %>%
  mutate(dat = map(filters, ~filter(t1, ..1)))
  • Related