Say I have a nested list with a bunch of data frames at different levels. I want to extract out flattened list of just the data frames. How might I write this using purrr
functions? Should I be looking at reduce
?
For example, given the data:
s <- list(x = 1:10,
data = data.frame(report = LETTERS[1:5],
value = rnorm(5, 20, 5)),
report = list(A = data.frame(x = 1:3, y = c(2, 4, 6)),
B = data.frame(x = 1:3, y = c(3, 6, 9)),
z = 4:10,
other = data.frame(w = 3:5,
color = c("red", "green", "blue"))))
I'd like the function to return:
list(data = data.frame(report = LETTERS[1:5],
value = rnorm(5, 20, 5)),
`report$A` = data.frame(x = 1:3, y = c(2, 4, 6)),
`report$B` = data.frame(x = 1:3, y = c(3, 6, 9)),
`report$other` = data.frame(w = 3:5,
color = c("red", "green", "blue")))
I've written a recursive function:
recursive_keep <- function(.x, .f) {
loop <- function(.y) {
if(is.list(.y)) {
c(keep(.y, .f), flatten(map(discard(.y, .f), loop)))
} else if(.f(.y)) {
.y
} else {
NULL
}
}
loop(.x)
}
It can be called as:
recursive_keep(s, is.data.frame)
It seems to work on this example, but it doesn't keep the name information. I'm looking to keep enough information that I could pluck the data from the original object. Maybe that is an easier question to answer?
loop()
and notrecursive_keep <- function(.y, .f) { if(is.list(.y)) { c(keep(.y, .f), flatten(map(discard(.y, .f), recursive_keep, .f))) } else if(.f(.y)) { .y } else { NULL } }
? – Cordlesskeep(rlang::squash(s), is.data.frame)
is not an answer to your question, but gives the same output as yourrecursive_keep()
. – Cordless