2

I perform a function multiple times with different outputs as exemplified.

require(data.table)
myfunction<-function(x){
DT1<-data.table(a=c(1,2,3),b=c("a","b","c"))
DT2<-data.table(d=c(4,5,6), e=c("d","e","f"))
return(list(DT1=DT1, DT2=DT2))
}
result<-lapply(1:2, myfunction)

I want to bind results. The desired output will be as the one I am showing. My real example uses hundreds of tables.

l1<-rbindlist(list(result[[1]]$DT1, result[[2]]$DT1), idcol = TRUE)
l2<-rbindlist(list(result[[1]]$DT2, result[[2]]$DT2), idcol = TRUE)
DESIRED_OUTPUT<-list(l1, l2)

I use this option but is not working: rbindlist data.tables wtih different number of columns

======================================================================

Update

The option that @nicola proposed doesn´t work when the number of elements of the list was diferent than 2. For the first example (DT1 and DT2). As a solution I create a variable "l" that calculate the number of elements inside the list of the function.

New example with solution.

require(data.table)
myfunction<-function(x){
DT1<-data.table(a=c(1,2,3),b=c("a","b","c"))
DT2<-data.table(d=c(4,5), e=c("d","e"))
DT3<-data.table(f=c(7,8,NA,9), g=c("g","h","i","j"))
return(list(DT1=DT1, DT2=DT2, DT3=DT3))
}
result<-lapply(1:5, myfunction)

l<-unique(sapply(result, length))
apply(matrix(unlist(result,recursive=FALSE),nrow=l),1,rbindlist,idcol=TRUE)
Community
  • 1
  • 1
Ushuaia81
  • 495
  • 1
  • 6
  • 14

2 Answers2

1

An attempt that should match on names of the list components:

Map(
  function(LL,n) rbindlist(unname(LL[names(l) %in% n]), idcol=TRUE),
  list(unlist(result, recursive=FALSE)),
  unique(names(l))
)

#[[1]]
#   .id a b
#1:   1 1 a
#2:   1 2 b
#3:   1 3 c
#4:   2 1 a
#5:   2 2 b
#6:   2 3 c
#
#[[2]]
#   .id d e
#1:   1 4 d
#2:   1 5 e
#3:   1 6 f
#4:   2 4 d
#5:   2 5 e
#6:   2 6 f
thelatemail
  • 91,185
  • 12
  • 128
  • 188
1

Here's an option:

do.call(function(...) Map(function(...) rbind(..., idcol = T), ...), result)
#$DT1
#   .id a b
#1:   1 1 a
#2:   1 2 b
#3:   1 3 c
#4:   2 1 a
#5:   2 2 b
#6:   2 3 c
#
#$DT2
#   .id d e
#1:   1 4 d
#2:   1 5 e
#3:   1 6 f
#4:   2 4 d
#5:   2 5 e
#6:   2 6 f

Here's another:

lapply(purrr::transpose(result), rbindlist, idcol = T)
eddi
  • 49,088
  • 6
  • 104
  • 155