Filtering lists using purrr

I have a list that I am trying to filter to remove varying numbers of elements from each item. I clearly don't have the correct approach here using purrr; is this because filter doesn't work on lists? Very grateful for any suggestions:

library(purrr)

test <- list(first = c("a", "b", "c", "d", "e", "f", "g", "h"),
             second = c("f", "g", "h", "i", "j", "k", "l", "m"),
             third = c("m", "n", "o", "p", "q", "r", "s", "t"))

todrop <- c("g", "l", "m")

out <- map(test, ~ filter(., %in% todrop))

#> Error: <text>:9:30: unexpected SPECIAL
#> 8: 
#> 9: out <- map(test, ~ filter(., %in%
#>                                 ^
Created on 2018-08-22 by the reprex package (v0.2.0).

In purrr you have discard that could help

library(purrr)

test <- list(first = c("a", "b", "c", "d", "e", "f", "g", "h"),
                         second = c("f", "g", "h", "i", "j", "k", "l", "m"),
                         third = c("m", "n", "o", "p", "q", "r", "s", "t"))

todrop <- c("g", "l", "m")

out <- map(test, ~ discard(.x, ~ .x %in% todrop))
out
#> $first
#> [1] "a" "b" "c" "d" "e" "f" "h"
#> 
#> $second
#> [1] "f" "h" "i" "j" "k"
#> 
#> $third
#> [1] "n" "o" "p" "q" "r" "s" "t"

Created on 2018-08-22 by the reprex package (v0.1.1.9000).

5 Likes

Thanks - that's really helpful.

Interestingly, I initially thought your solution didn't work. But then realised that the scales package (which I also had loaded for my main analysis) also has a discard function.

using purrr::discard() solved the problem.

Many thanks for your help!

2 Likes

You can also use base R functions if you want to avoid conflicts.

library(purrr)

test <- list(first = c("a", "b", "c", "d", "e", "f", "g", "h"),
                         second = c("f", "g", "h", "i", "j", "k", "l", "m"),
                         third = c("m", "n", "o", "p", "q", "r", "s", "t"))

todrop <- c("g", "l", "m")

# use of vectorize fonction
map(test, ~ setdiff(.x, todrop))
#> $first
#> [1] "a" "b" "c" "d" "e" "f" "h"
#> 
#> $second
#> [1] "f" "h" "i" "j" "k"
#> 
#> $third
#> [1] "n" "o" "p" "q" "r" "s" "t"
# use of subsetting
map(test, ~ .x[!.x %in% todrop])
#> $first
#> [1] "a" "b" "c" "d" "e" "f" "h"
#> 
#> $second
#> [1] "f" "h" "i" "j" "k"
#> 
#> $third
#> [1] "n" "o" "p" "q" "r" "s" "t"

Created on 2018-08-22 by the reprex package (v0.1.1.9000).

4 Likes