diff --git a/R/data.table.R b/R/data.table.R index c3e85fb44..23c4c6bec 100644 --- a/R/data.table.R +++ b/R/data.table.R @@ -1573,24 +1573,72 @@ as.data.table.data.frame = function(x, keep.rownames=FALSE) alloc.col(ans) } -as.data.table.list = function(x, keep.rownames=FALSE) { +as.data.table.list = function(x, keep.rownames=FALSE, bind.using=c("cbind", "rbind")) { if (!length(x)) return( null.data.table() ) - n = vapply(x, length, 0L) - mn = max(n) - x = copy(x) - if (any(n 2)) { + inds.arrays <- which(dims > 2) + ## If cbind'ing, then the "number of rows" is the product of all dimensions other than columns + ## If rbind'ing, then the "number of cols" is the product of all dimensions other than rows + ## 'd' is the dim being "preserved" (ie, either rows or cols) + d <- if (bind.using == "cbind") 1 else 2 + for (i in inds.arrays) { + dim.i <- attr(x[[i]], "dim") + setattr( x[[i]], "dim", c(dim.i[d], prod(dim.i[-d])) ) + } } + + ## check for consisent length/rows/cols + ## 'L' will store the "size" (either length, rows or cols + ## depending on the element of x and the function in bind.func) + hasdim <- dims != 0 + L <- vector("integer", length=length(x)) + L[!hasdim] <- vapply(x[!hasdim], length, 0L) + ## use either nrow() or ncol() depending on bind.func + n_row_or_col <- if (bind.using == "cbind") nrow else ncol + L[hasdim] <- vapply(x[hasdim], n_row_or_col, 0L) + ## Test that L are all equal (ie min, max, mean are all the same) + if (any(range(L) != mean(L))) + stop(sprintf("arguments imply differing number of %s: %s\n\nMore Info: 'x', the list provided to as.data.table(), has at least one element that is two-dimensional. For consistency with as.data.frame, there is no recycling when the number of %1$s / length of each element of x are not all the same.\nYou may want to consider: do.call(cbind, x)", ifelse(bind.using == "cbind", "rows", "cols"), paste(L, collapse=", "))) + + return(as.data.table(do.call(bind.func, x))) + } else { + ## Proceed as "normal" (prior to Implementing #833) + n = vapply(x, length, 0L) + mn = max(n) + x = copy(x) + + if (any(n