How to simplify a nested list in R?

I have a nested list:

nested_list <- list(a = c(1,2), b = list( c = c(3,4), d = list( e = c(5,6,7) ))) 

I want to simplify it so that it looks like this (only one level, nested names are grouped using colons):

 simplified_list <- list(a = c(1,2), "b:c" = c(3,4), "b:d:e" = c(5,6,7) ) 

What is the best way to do this?

+7
list r
source share
5 answers

This approach is quite short. It does not use any packages. It assumes that input names do not contain trailing digits:

 u <- unlist(nested_list) res <- tapply(u, sub("\\d+$", "", names(u)), unname) 

giving:

 > res $a [1] 1 2 $bc [1] 3 4 $bde [1] 5 6 7 

If it is important that the names are separated: instead. then add this:

 names(res) <- chartr(".", ":", names(res)) 
+8
source share

I do not pretend to be the "best", but it works:

 d <- reshape2::melt(nested_list) > d value L3 L2 L1 1 1 <NA> <NA> a 2 2 <NA> <NA> a 3 3 <NA> cb 4 4 <NA> cb 5 5 edb 6 6 edb 7 7 edb > d$L <- apply(d[,c('L1','L2','L3')],1,function(x) paste(unique(x[!is.na(x)]),collapse = ":")) > l <- plyr::dlply(d,"L",function(x) unlist(x$value)) > l $a [1] 1 2 $`b:c` [1] 3 4 $`b:d:e` [1] 5 6 7 
+3
source share

I was too slow, but maybe my solution still helps. This is somewhat longer than joran's, but (at least for me) seems more understandable. (But perhaps this is because I'm not too familiar with the plyr package.) I will definitely not argue that this is the best solution ...

 # create names for the list nm <- names(unlist(nested_list)) nm <- unique(sub("[0-9]*$","",nm)) nm <- gsub("\\.",":",nm) # construct list new_list <- lapply(nm,function(n) { nested_list[[strsplit(n,":")[[1]]]] }) # apply names names(new_list) <- nm > new_list $a [1] 1 2 $`b:c` [1] 3 4 $`b:d:e` [1] 5 6 7 
+3
source share

Another option:

 nested_list <- list(a = c(1,2), b = list( c = c(3,4), d = list( e = c(5,6,7) ))) ul <- unlist(nested_list) sp <- split(unname(ul), gsub('\\d', '', names(ul))) `names<-`(sp, gsub('\\.', ':', names(sp))) # $a # [1] 1 2 # # $`b:c` # [1] 3 4 # # $`b:d:e` # [1] 5 6 7 
+3
source share

I ran into the LinearizeNestedList Akhil S Bhel function a while ago and saved it as a Gist. It seems to do what you ask for:

 LinearizeNestedList(nested_list, NameSep = ".") # $a # [1] 1 2 # # $bc # [1] 3 4 # # $bde # [1] 5 6 7 
+3
source share

All Articles