Home > Enterprise >  Merge inner nested lists elements by name
Merge inner nested lists elements by name

Time:09-11

I have already asked this question but wasn't well presented, so I decided to ask again from scratch.

I have a Large List object in R containing 100 lists of outputs of different models, each output is itself a list containing the statistics for all the parameters of the model. So I have a sublist for the means, one for sd, etc, inside each one of the 100 outputs lists. Each statistics have a vector or matrix for each parameter of the model. What I want is to merge all the 100 lists outputs in one single large list by aggregating them based on their statistics and parameters names.


modeloutputs <- list("model1"=list("simlist"=list("N"=c(1,2,3,4,5,6,7), "sigma"=c(1,2,3,4), "theta"=c(7,8,9)),
                                   "sd" = list("N"=c(6), "sigma"=c(6.5), "theta"=matrix(6:11, nrow = 2, ncol = 3)), 
                                   "mean" = list("N"=c(3), "sigma"=c(3.5), "theta"=matrix(6:11, nrow = 2, ncol = 3))),
                     "model2"=list("simlist"=list("N"=c(8,9,10,11,12,13,14), "sigma"=c(1,2,3,4), "theta"=c(7,8,9)),
                                   "sd" = list("N"=c(7), "sigma"=c(8.5), "theta"=matrix(6:11, nrow = 2, ncol = 3)), 
                                   "mean" = list("N"=c(5), "sigma"=c(5.5), "theta"=matrix(6:11, nrow = 2, ncol = 3))),
                     "model3"=list("simlist"=list("N"=c(15,16,17,18,19,20,21), "sigma"=c(1,2,3,4), "theta"=c(7,8,9)),
                                   "sd" = list("N"=c(8), "sigma"=c(8.5), "theta"=matrix(6:11, nrow = 2, ncol = 3)), 
                                   "mean" = list("N"=c(9), "sigma"=c(9.5), "theta"=matrix(6:11, nrow = 2, ncol = 3))))


modeloutputs_wanted <- list("allmodels"=list("simlist"=list("N"=c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21), "sigma"=c(1,2,3,4,1,2,3,4,1,2,3,4), "theta"=c(7,8,9,7,8,9,7,8,9)),
                                   "sd" = list("N"=c(6,7,8), "sigma"=c(6.5,8.5,8.5), "theta"=matrix(6:11, nrow = 2, ncol = 3)), 
                                   "mean" = list("N"=c(3,5,9), "sigma"=c(3.5,5.5,9.5), "theta"=matrix(6:11, nrow = 2, ncol = 3))))


theta should have all the matrixes concatenated by row like a rowbind(), I wasn't able to reproduce it correctly in the example.

CodePudding user response:

This is close to what you're looking for:

library(purrr)
transpose(modeloutputs) |>
  map(~ transpose(.x)) %>% 
  map_depth(2, ~ if(all(sapply(.x, is.matrix))) unique(.x) else reduce(.x, c))

output

$simlist
$simlist$N
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
[21] 21

$simlist$sigma
 [1] 1 2 3 4 1 2 3 4 1 2 3 4

$simlist$theta
[1] 7 8 9 7 8 9 7 8 9


$sd
$sd$N
[1] 6 7 8

$sd$sigma
[1] 6.5 8.5 8.5

$sd$theta
$sd$theta[[1]]
     [,1] [,2] [,3]
[1,]    6    8   10
[2,]    7    9   11



$mean
$mean$N
[1] 3 5 9

$mean$sigma
[1] 3.5 5.5 9.5

$mean$theta
$mean$theta[[1]]
     [,1] [,2] [,3]
[1,]    6    8   10
[2,]    7    9   11

CodePudding user response:

or in base R:

agg_list <- list()
for(statistic in lapply(modeloutputs, names)[[1]]){
  theta_vec<- c()
  theta <- matrix(ncol=3)
  N_vec<- c()
  sigma_vec<- c()
  for(model in names(modeloutputs)){
    if(statistic == "simlist"){
      theta_vec <- c(theta_vec, modeloutputs[[model]][[statistic]][["theta"]])
      sigma_vec <- c(sigma_vec, modeloutputs[[model]][[statistic]][["sigma"]])
      N_vec <- c(N_vec, modeloutputs[[model]][[statistic]][["N"]])
      stats <-list("N"=N_vec, "sigma"=sigma_vec, "theta"=theta_vec )
    }else{
      theta <- rbind(theta, modeloutputs[[model]][[statistic]][["theta"]])
      theta <- na.omit(theta)
      sigma_vec <- c(sigma_vec, modeloutputs[[model]][[statistic]][["sigma"]])
      N_vec <- c(N_vec, modeloutputs[[model]][[statistic]][["N"]])
      stats <- list("N"=N_vec, "sigma"=sigma_vec, "theta"=theta )
    }
  }
  agg_list <- append(agg_list , list(stats))
}
names(agg_list) <- sapply(modeloutputs, names)[,1]

But admittedly the answer by @Maël is much more elegant :)

  • Related