How to write a recursive version of purrr :: keep?

Let's say I have a nested list with many data frames at different levels. I want to extract a flattened list of only data. How can I write this using purrr functions? Should I look 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 want to return a function:

 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 wrote 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 the following:

 recursive_keep(s, is.data.frame) 

It seems to be working on this example, but it does not save title information. I want to keep enough information so that I can wrest data from the original object. Maybe this is a simpler question?

+5
source share
1 answer

This one-line body recursive function stores names and does not use packages:

 rec <- function(x, FUN = is.data.frame) if (FUN(x)) list(x) else if (is.list(x)) do.call("c", lapply(x, rec, FUN)) str(rec(s)) # test 

(continued after the release):

 List of 4 $ data :'data.frame': 5 obs. of 2 variables: ..$ report: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5 ..$ value : num [1:5] 29.1 19.9 21.2 13 25.2 $ report.A :'data.frame': 3 obs. of 2 variables: ..$ x: int [1:3] 1 2 3 ..$ y: num [1:3] 2 4 6 $ report.B :'data.frame': 3 obs. of 2 variables: ..$ x: int [1:3] 1 2 3 ..$ y: num [1:3] 3 6 9 $ report.other:'data.frame': 3 obs. of 2 variables: ..$ w : int [1:3] 3 4 5 ..$ color: Factor w/ 3 levels "blue","green",..: 3 2 1 

Regarding getting, say, A from report from source object s :

 s[["report"]][["A"]] 

or

 ix <- c("report", "A") s[[ix]] 
+3
source

Source: https://habr.com/ru/post/1274475/


All Articles