Home > Software engineering >  Running a for loop for a list having multiple lists inside
Running a for loop for a list having multiple lists inside

Time:07-30

Following this topic bind_row datafrane within a list in r I would like to ask about doing a for loop for a list containing multiple lists.

#first list
x1 <- data.frame(rnorm(5), rnorm(5))
x2 <- data.frame(rnorm(5), rnorm(5))
x3 <- data.frame(rnorm(5), rnorm(5))

list1 <- list(x1,x2,x3)

#second list
x4 <- data.frame(rnorm(6), rnorm(6))
x5 <- data.frame(rnorm(6), rnorm(6))
x6 <- data.frame(rnorm(6), rnorm(6))

list2 <- list(x4,x5,x6)

#third list
x7 <- data.frame(rnorm(7), rnorm(7))
x8 <- data.frame(rnorm(7), rnorm(7))
x9 <- data.frame(rnorm(7), rnorm(7))

list3 <- list(x7,x8,x9)

biglist <- list(list1, list2,list3)

For single list (e.g. list1) I was trying to combine x1 to x2 and x3 respectivelly using for loop with bind_row function like this:

df <- list()
for(i in 2:length(list1)){
  df[[i - 1]] <- dplyr::bind_rows(list1[[1]], list1[[i]])
}

I replicated this step for all lists I have by using this code follows

biglist1 <- list()
df <- list()

for(i in 1:length(biglist)){
  biglist1[[i]] <- biglist[[i]]
  for(j in 2:length(biglist1[[i]])) {
    df[[i]] <- bind_rows(biglist1[[i]][[1]], biglist1[[i]][[j]])
  }}

My desired output is to have a list having 4 lists that have 2 datafarmes. However, the output I got so far only have one dataframe. Anyone enlighten me please? Thank you in advance!

CodePudding user response:

To combine the first element of a list with each of the others, we can use lapply like so

lapply(biglist, function(x){
    lapply(seq_along(x)[-1], function(i) {
        dplyr::bind_rows(x[[1]], x[[i]])
    })
})

Following the same logic, this can be re-written to a for loop:

out <- list()
for (i in seq_along(biglist)) {
    first <- biglist[[i]][[1]]
    l <- list()
    for (j in seq_along(biglist[[i]][-1])) {
        l[[j]] <- dplyr::bind_rows(first, biglist[[i]][[j   1]])
    }
    out[[i]] <- l
}

CodePudding user response:

Your loop is almost there, but there was a few mistakes the indexing, and instead of the df-list, you'd want to make your biglist1 into a list-of-lists, before applying the logic of your code from the single case. I.e.

biglist1 <- list()

for (i in 1:length(biglist)) {
    
  biglist1[[1]] <- list()
  
  for(j in 2:length(biglist[[i]])) 
    biglist1[[i]][[j - 1]] <- bind_rows(biglist[[i]][[1]], biglist[[i]][[j]])
  
}

You could also simply wrap your for-loop into an lapply (as indicated by your tag) and return the df (or go the full way as described by @Donald Seinen with two times lapply):

lapply(biglist, \(list1) {
                          df <- list()
                          for (i in 2:length(list1))
                            df[[i - 1]] <- dplyr::bind_rows(list1[[1]], list1[[i]])
                          return(df)
                          }
       )
  • Related