Mohan Govindasamy
Mohan Govindasamy

Reputation: 906

How to use `dplyr::filter` inside `purrr::map`

Here is a very simple function which returns a list when using map

library(tidyverse)


simple_function <- function(x,y){
 c(x+y, y-x)
}


1:3 %>% 
  map2(5,simple_function)
#> [[1]]
#> [1] 6 4
#> 
#> [[2]]
#> [1] 7 3
#> 
#> [[3]]
#> [1] 8 2

I want to create a similar function which can filter based on a keyword and returns a vector. So this is what I made



df <- structure(list(to_filter = c("YY", "XX", "XX", "YY", "XX", "XX", 
                                 "YY", "YY", "YY", "YY", "ZZ", "YY", "ZZ", "YY", "YY", "XX", "YY", 
                                 "YY", "YY", "YY"), num = c(1L, 2L, 2L, 4L, 2L, 3L, 3L, 5L, 3L, 
                                                            1L, 4L, 5L, 1L, 2L, 5L, 1L, 1L, 3L, 5L, 5L)), row.names = c(NA, 
                                                                                                                        -20L), class = c("tbl_df", "tbl", "data.frame"))

filter_func <- function(name, dff){
  dff %>% 
    filter(to_filter == name) %>% 
    pull(num)
}

As you can see the function works fine when I use it alone

filter_func("YY", df)
#>  [1] 1 4 3 5 3 1 5 2 5 1 3 5 5

But when I use this in a map it is not working


df %>% 
  pull(to_filter) %>% 
  unique() %>% 
  map2(df, filter_func)
#> Error: Mapped vectors must have consistent lengths:
#> * `.x` has length 3
#> * `.y` has length 2

I know I'm making a very basic mistake here but couldn't figure out what.

Upvotes: 0

Views: 673

Answers (2)

Nicol&#225;s Velasquez
Nicol&#225;s Velasquez

Reputation: 5908

I don't see why you need map2(), which requires two lists. You might run it with map(). That said, you do need to specify fliter_func()'s dff value.

df %>% 
    pull(to_filter) %>% 
    unique() %>% 
    map(.f = filter_func, dff = df)

[[1]]
 [1] 1 4 3 5 3 1 5 2 5 1 3 5 5

[[2]]
[1] 2 2 2 3 1

[[3]]
[1] 4 1

Upvotes: 2

Sinh Nguyen
Sinh Nguyen

Reputation: 4497

You need map with proper function call instead of map_2

df %>% 
  pull(to_filter) %>% 
  unique() %>% 
  map(., .f = function(x) { filter_func(name = x, dff = df) })

Output

[[1]]
 [1] 1 4 3 5 3 1 5 2 5 1 3 5 5

[[2]]
[1] 2 2 2 3 1

[[3]]
[1] 4 1

Upvotes: 2

Related Questions