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)
}
)