I would like to convert nested list like this:
l <- list(A=list(a=list(1),b=list(2)),
B=list(cd=list(c=list(3,4,5),d=list(6,7,8)),e=list(c(9,10))))
into list
o <- list(A=c(1,2),A.a=1,A.b=2,B=c(3:10),
B.cd=c(3:8),B.cd.c=c(3:5),B.cd.d=c(6:8),B.e=c(9:10))
At each list level values from nested lists should be concatenated.
First, flatten the nested lists. Take Intersection using filter() and save it to 'lst3'. Now find elements either not in lst1 or in lst2, and save them to 'temp'. Finally, append 'temp' to 'lst3'.
If some of the elements in the series object have lists, then we can unnest those list elements into multiple rows of the series object. Unnesting is nothing but exploding the lists into rows. So this transformation can be done easily with the help of the pandas series.
Use the sum() function to concatenate nested lists to a single list by passing an empty list as a second argument to it.
Clearly a case for a recursive function, but getting the return values to unlist properly is tricky. Here's a function that will do it; it doesn't get the names quite right but that's easily fixed afterwards.
unnest <- function(x) {
if(is.null(names(x))) {
list(unname(unlist(x)))
}
else {
c(list(all=unname(unlist(x))), do.call(c, lapply(x, unnest)))
}
}
Output from unnest(l)
is
$all
[1] 1 2 3 4 5 6 7 8 9 10
$A.all
[1] 1 2
$A.a
[1] 1
$A.b
[1] 2
$B.all
[1] 3 4 5 6 7 8 9 10
$B.cd.all
[1] 3 4 5 6 7 8
$B.cd.c
[1] 3 4 5
$B.cd.d
[1] 6 7 8
$B.e
[1] 9 10
and can be massaged into your desired output with
out <- unnest(l)
names(out) <- sub("\\.*all", "", names(out))
out[-1]
To not recurse when there's only one element, try
unnest2 <- function(x) {
if(is.null(names(x)) | length(x)==1) {
list(unname(unlist(x)))
} else {
c(list(all=unname(unlist(x))), do.call(c, lapply(x, unnest2)))
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With