Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

From a two-level list with the same structure for all items, bind together all like-named items from that second level

I’ve got a list with a uniform structure: each item is itself a list of commonly named data.frames. I want to find all the items with the same name in the 2nd level and make them a single data.frame. Here’s an example list like this:

MyList <- list("A" = list("apples" = data.frame(X = 1:5, 
                                            Source = "A"), 
                      "mangoes" = data.frame(X = 1:5, 
                                             Source = "A")), 
           "B" = list("apples" = data.frame(X = 1:5, 
                                            Source = "B"), 
                      "mangoes" = data.frame(X = 1:5, 
                                             Source = "B")), 
           "C" = list("apples" = data.frame(X = 1:5, 
                                            Source = "C"), 
                      "mangoes" = data.frame(X = 1:5, 
                                             Source = "C")))

I’d like to create a new list with a single level instead of two levels, and I need all the "apples" to be a single data.frame and all the "mangoes" to be a single data.frame. It would look like this:

MyNewList <- list("apples" = bind_rows(data.frame(X = 1:5, 
                                              Source = "A"), 
                                   data.frame(X = 1:5, 
                                              Source = "B"), 
                                   data.frame(X = 1:5, 
                                              Source = "C")), 
              "mangoes" = bind_rows(data.frame(X = 1:5, 
                                               Source = "A"), 
                                    data.frame(X = 1:5, 
                                               Source = "B"), 
                                    data.frame(X = 1:5, 
                                               Source = "C")))

This seems like a job for map or pluck from purrr, but I’ve always found the syntax for those to be confusing. Here’s what I’ve tried:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Trying to get all the "apples" as a place to start:

 pluck(MyList, 1:3, "apples") # nope; index can't have length > 1

Maybe I can lapply over the names of the items?

 lapply(c("apples", "mangoes"), 
        FUN = function(x) pluck(MyList, x)) # all items are NULL

Maybe map_depth does this?

 map_depth(.x = MyList, 
      .depth = 2, 
      .f = bind_rows) # not at all what I want

>Solution :

You can iterate over each fruit to bind it into a data frame:

fruits  <- c("apples", "mangoes")
out  <- lapply(fruits, \(fruit)
    dplyr::bind_rows(lapply(MyList, \(x) x[[fruit]]))
)  |> setNames(fruits)

identical(out, desired)
# [1] TRUE
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading