Search code examples
rpurrr

How to name highest level of lists created within a purr function


I am using purrr to iteratively apply functions to sf objects based on different aoi, and store the outputs in lists, however I cannot assign names to the top level of nested lists. I don't think think the sf objects are relevant to the problem, but including a sf based example just in case. IN my desried output I could query the list by region name to pull out both the region and state sublists to pass to other mapping functions, and the second mapview call at the end of code would produce same result as the call using index numbers on the same list.

#set things up
library(spData)
library(sf)
library(tidyverse)
library(mapview)

STATES <- spData::us_states %>%
  mutate(REGION=as.character(REGION))


REGIONS <- STATES %>%
  group_by(REGION) %>%
    summarise() %>%
  group_by(REGION) %>%
  group_split(.keep = T) %>%
    set_names(.,nm=map(.,\(x)first(x$REGION)))


REGIONS_INTERSECT <- REGIONS %>%
  map( \(x) st_intersection(STATES, x))


REGION_NAMES <- as.character(STATES$REGION) %>%
  unique()


##desired format but top level list not named


OUT_LIST <- map(REGION_NAMES, \(x){
  REGION_LIST <- REGIONS[x] %>%
    set_names(nm="Region")
  STATE_LIST <- REGIONS_INTERSECT[x] %>%
    set_names(nm="State")
  
  OUTPUT <-  c(REGION_LIST, STATE_LIST )
    
  
  return(OUTPUT)
  
}) 

##changes lower level names 


OUT_LIST <- map(REGION_NAMES, \(x){
  REGION_LIST <- REGIONS[x] %>%
    set_names(nm="Region")
  STATE_LIST <- REGIONS_INTERSECT[x] %>%
    set_names(nm="State")
  
  OUTPUT <-  c(REGION_LIST, STATE_LIST ) %>%
    set_names(.,nm=x)
  
  
  return(OUTPUT)
  
}) 



##alos changes lower level names 


OUT_LIST <- map(REGION_NAMES, \(x){
  REGION_LIST <- REGIONS[x] %>%
    set_names(nm="Region")
  STATE_LIST <- REGIONS_INTERSECT[x] %>%
    set_names(nm="State")
  
  x <-  c(REGION_LIST, STATE_LIST ) 
  
  
  return(OUTPUT)
  
}) 

##only changes one lower level names 


OUT_LIST <- map(REGION_NAMES, \(x){
  REGION_LIST <- REGIONS[x] %>%
    set_names(nm="Region")
  STATE_LIST <- REGIONS_INTERSECT[x] %>%
    set_names(nm="State")
  
  OUTPUT <-  c(REGION_LIST, STATE_LIST ) 
  
   names(OUTPUT)<-x
  
  return(OUTPUT)
  
}) 





###in desired output these two functions woudl have same output

mapview(OUT_LIST[[1]][[1]])+mapview(OUT_LIST[[1]][[2]], col.regions="red")


mapview(OUT_LIST[["South"]][["Region"]])+mapview(OUT_LIST[["South"]][["State"]], col.regions="red")

Solution

  • If the input vector is named, the output of map() will have the same names. So you can just name your vector of regions with purrr::set_names(REGION_NAMES) (or setNames(nm = REGION_NAMES)):

    OUT_LIST <- map(set_names(REGION_NAMES), \(x){
      REGION_LIST <- REGIONS[x] %>%
        set_names(nm="Region")
      STATE_LIST <- REGIONS_INTERSECT[x] %>%
        set_names(nm="State")
      
      c(REGION_LIST, STATE_LIST)
    }) 
    
    names(OUT_LIST)
    # "South"    "West"     "Norteast" "Midwest"