rdataframetidyrpurrr

Extracting & Joining Values from a Nested List to a single column in R


I have a deeply nested list that I am trying to extract into a simple df.

Sample List

df <- tibble::tribble(
     ~division,  ~id,                                                                                                                                                                                                                                                           ~owners,
  "Division 2",  "8",                                                                                                                                   list(list(commissioner = 0, name = "Jesse H", id = "475A2F18-B6AF-11E6-977B-8468E8194D12", playoff_add_drops_disabled = 0)),
  "Division 1", "15",                                                                                                                                list(list(commissioner = 0, name = "Jon O", id = "F37E4A84-673C-11EC-812D-82AF546C6EE5", playoff_add_drops_disabled = 0)),
  "Division 2", "10", list(list(commissioner = 0, name = "Jim K", id = "1F19EADA-AC9D-11E3-8EB7-031CFC5F1C7D", playoff_add_drops_disabled = 0), list(commissioner = 0, name = "Kevin P", id = "E48FCF2A-ACA5-11E3-854D-2A588E5A61DF", playoff_add_drops_disabled = 0)),
  "Division 1", "14",       list(list(commissioner = 0, name = "Alan C", id = "D97B1226-E9C6-11E8-8119-3A141D7BE3A7", playoff_add_drops_disabled = 0), list(commissioner = 0, name = "Sam L", id = "8CC10D94-E7DF-11EC-9CA5-51CD4E0A8531", playoff_add_drops_disabled = 0)),
  "Division 1",  "9",                                                                                                                                  list(list(commissioner = 0, name = "Don R", id = "4686110A-D916-11EF-8988-87BD04866ADA", playoff_add_drops_disabled = 0)),
  "Division 1", "17",                                                                                                           list(list(logged_in_owner = 1, commissioner = 0, name = "Jason S", id = "2E84EA94-D98A-11EF-A9AB-4A2105866ADA", playoff_add_drops_disabled = 0)),
  "Division 2", "16",                                                                                                                                   list(list(commissioner = 0, name = "Eric W", id = "E0D804E0-9B59-11ED-BA80-FCF8D3963504", playoff_add_drops_disabled = 0)),
  "Division 1",  "3",                                                                                                                                 list(list(commissioner = 0, name = "James C", id = "1EF701E6-AC9D-11E3-8EB7-031CFC5F1C7D", playoff_add_drops_disabled = 0)),
  "Division 2", "13",                                                                                                                                 list(list(commissioner = 0, name = "Enrique D", id = "1F2EBB68-AC9D-11E3-8EB7-031CFC5F1C7D", playoff_add_drops_disabled = 0)),
  "Division 1",  "5",                                                                                                                                list(list(commissioner = 0, name = "Mitch T", id = "1F00CD8E-AC9D-11E3-8EB7-031CFC5F1C7D", playoff_add_drops_disabled = 0)),
  "Division 2",  "1",           list(list(commissioner = 1, name = "Fred R", id = "1E34F182-AC9D-11E3-8EB7-031CFC5F1C7D", playoff_add_drops_disabled = 0), list(commissioner = 0, name = "Cam E", id = "E42646B8-ACA5-11E3-854D-2A588E5A61DF", playoff_add_drops_disabled = 0)),
  "Division 2", "12",                                                                                                                         list(list(commissioner = 0, name = "Nick D", id = "1F29D4C2-AC9D-11E3-8EB7-031CFC5F1C7D", playoff_add_drops_disabled = 0)),
  "Division 1",  "4",                                                                                                                                    list(list(commissioner = 0, name = "Liam S", id = "389BDCA0-21EC-11EA-AD4E-B4851D7BE3A7", playoff_add_drops_disabled = 0)),
  "Division 2",  "7",                                                                                                                              list(list(commissioner = 0, name = "David E", id = "3D994500-AE62-11E5-AB74-A57DE140860F", playoff_add_drops_disabled = 0))
  )

I want to extract the commissioner and name values and put them in the same level as division and id. I'd like the name column to become owner_name, and have any row that has more than one value be joined with a &. For example on the row with id = "1". owner_name would be "Fred R & Cam E".


Solution

  • You can use various map functions.

    library(tidyverse)
    
    df %>%
      mutate(map_dfc(c(commissioner = "commissioner", owner_name = "name"),
             ~ map_chr(map_depth(owners, 2, .x), paste, collapse = ' & ')),
             .keep = "unused")
    
    # # A tibble: 14 × 4
    #    division   id    commissioner owner_name     
    #    <chr>      <chr> <chr>        <chr>          
    #  1 Division 2 8     0            Jesse H        
    #  2 Division 1 15    0            Jon O          
    #  3 Division 2 10    0 & 0        Jim K & Kevin P
    #  4 Division 1 14    0 & 0        Alan C & Sam L 
    #  5 Division 1 9     0            Don R          
    #  6 Division 1 17    0            Jason S        
    #  7 Division 2 16    0            Eric W         
    #  8 Division 1 3     0            James C        
    #  9 Division 2 13    0            Enrique D      
    # 10 Division 1 5     0            Mitch T        
    # 11 Division 2 1     1 & 0        Fred R & Cam E 
    # 12 Division 2 12    0            Nick D         
    # 13 Division 1 4     0            Liam S         
    # 14 Division 2 7     0            David E