I have a list called master, which contains three IDs:
master = list(p1 = list(id = 'abc'), p2 = list(id = 'def'), p3 = list(id = 'ghi'))
str(master)
List of 3
 $ p1:List of 1
  ..$ id: chr "abc"
 $ p2:List of 1
  ..$ id: chr "def"
 $ p3:List of 1
  ..$ id: chr "ghi"
To each level 1 element of this list, I would like to append the corresponding value and radius elements from the val and rad lists:
val = list(p1 = list(value = 5), p3 = list(value = 8))
str(val)
List of 2
 $ p1:List of 1
  ..$ value: num 5
 $ p3:List of 1
  ..$ value: num 8
rad = list(p1 = list(radius = 2), p2 = list(radius = 10))
str(rad)
List of 2
 $ p1:List of 1
  ..$ radius: num 2
 $ p2:List of 1
  ..$ radius: num 10
I have to be careful to match the elements by name because val and rad do not have the same structure as master, i.e. val is missing a slot for p2 and rad is missing a slot for p3. 
I can use the following to partially achieve the desired result:
master_final = lapply(X=names(master),function(x, master, val, rad) c(master[[x]], val[[x]], rad[[x]]), master, val, rad)
str(master_final)
List of 3
 $ :List of 3
  ..$ id    : chr "abc"
  ..$ value : num 5
  ..$ radius: num 2
 $ :List of 2
  ..$ id    : chr "def"
  ..$ radius: num 10
 $ :List of 2
  ..$ id   : chr "ghi"
  ..$ value: num 8
But I would like each element of the resulting list to have the same structure, i.e. an id, value and radius slot. I am not sure how to do this in a way that generalises to any number of lists? I don't like having to write [[x]] for each list in the lapply function: function(x, master, val, rad) c(master[[x]], val[[x]], rad[[x]]). 
One way would be to convert the lists to dataframe and do a merge based on list name. We can then split the dataframe based on list_name.
df1 <- Reduce(function(x, y) merge(x, y, all = TRUE, by = "ind"), 
                     list(stack(master), stack(val),stack(rad)))
names(df1) <- c("list_name", "id", "value", "radius")
lapply(split(df1[-1], df1$list_name), as.list)
#$p1
#$p1$id
#[1] "abc"
#$p1$value
#[1] 5
#$p1$radius
#[1] 2
#$p2
#$p2$id
#[1] "def"
#$p2$value
#[1] NA
#$p2$radius
#[1] 10
#$p3
#$p3$id
#[1] "ghi"
#$p3$value
#[1] 8
#$p3$radius
#[1] NA
This keeps NA values in the list as it is, if we want to remove them the code becomes a bit ugly. 
lapply(split(df1[-1], df1$list_name), function(x) 
     {inds <- !is.na(x); as.list(setNames(x[inds], names(x)[inds]))})
                        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