I have a list of lists like the following:
testlist <- list(
list(aaa_x = 1, aaa_y = 2, aaa_z = 5, bbb_a = 333, bbb_b = 222),
list(aaa_x = 7, aaa_y = 5, aaa_z = 6, bbb_a = 3939, bbb_b = 5635)
)
I want to filter the lists contained in the list (actually, I want to split the list) on condition of name prefixes, so I thought of doing it this way:
testlist %>% map(keep(grepl(pattern="aaa", x=names(.))))
However, I end up with
Error in probe(.x, .p, ...) : argument ".p" is missing, with no default
while the following works (but is of course not sufficient):
testlist[[1]] %>% keep(grepl(pattern="aaa", x=names(.)))
There's probably a very nice, simple, tidy way to do it...
Thanks in advance!
Do you want the result to retain the current structure i.e. should it return a list of lists with only the elements named "aaa"?
yes, that's the goal. Sorry for not directly providing a desired result. I want it to look like this:
filteredlist <- list(
list(aaa_x = 1, aaa_y = 2, aaa_z = 5),
list(aaa_x = 7, aaa_y = 5, aaa_z = 6)
)
This ought to do the trick. You can substitute grepl()
for str_detect()
if you wish. I just like stringr
.
library(tidyverse)
testlist <- list(
list(aaa_x = 1, aaa_y = 2, aaa_z = 5, bbb_a = 333, bbb_b = 222),
list(aaa_x = 7, aaa_y = 5, aaa_z = 6, bbb_a = 3939, bbb_b = 5635)
)
map(testlist, ~ keep(.x, .p = str_detect(names(.x), "aaa")))
#> [[1]]
#> [[1]]$aaa_x
#> [1] 1
#>
#> [[1]]$aaa_y
#> [1] 2
#>
#> [[1]]$aaa_z
#> [1] 5
#>
#>
#> [[2]]
#> [[2]]$aaa_x
#> [1] 7
#>
#> [[2]]$aaa_y
#> [1] 5
#>
#> [[2]]$aaa_z
#> [1] 6
Created on 2020-05-22 by the reprex package (v0.3.0)
2 Likes
Works like a charm, thank you!
If you have the time to expand a bit, I'd like to understand what I did wrong with my example above.
So this one works
map(testlist, ~ keep(.x, .p = str_detect(names(.x), "aaa")))
while this one doesn't
map(testlist, keep(str_detect(names(.x), "aaa")))
So I need to turn it into a function/formula? I thought the whole point of map
was to supply the individual elements of the (first) argument to the (second) function?
I think it's more accurate to think of it the other way around i.e. map()
applies the function in .f
to each element of .x
.
# mean() is applied to each vector in the list.
purrr::map(.x = list(c(1:3), c(4:6)), .f = mean)
#> [[1]]
#> [1] 2
#>
#> [[2]]
#> [1] 5
Created on 2020-05-22 by the reprex package (v0.3.0)
However, for the problem at hand, we want to test whether each element meets a specified condition. In essence, we want to use the element as an argument in a function call. In order to do that, we need to define an anonymous function.
purrr
simply provides ~
as a shorthand to save typing. For example, the two calls below are equivalent.
library(tidyverse)
testlist <- list(
list(aaa_x = 1, aaa_y = 2, aaa_z = 5, bbb_a = 333, bbb_b = 222),
list(aaa_x = 7, aaa_y = 5, aaa_z = 6, bbb_a = 3939, bbb_b = 5635)
)
result_1 <- map(testlist, function(x) keep(x, .p = str_detect(names(x), "aaa")))
result_2 <- map(testlist, ~ keep(.x, .p = str_detect(names(.x), "aaa")))
identical(result_1, result_2)
#> [1] TRUE
Created on 2020-05-22 by the reprex package (v0.3.0)
1 Like
system
Closed
May 29, 2020, 12:12pm
7
This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.