Skip to content

Commit

Permalink
#833 - as.data.table.list handles matrices
Browse files Browse the repository at this point in the history
  • Loading branch information
rsaporta committed Sep 28, 2014
1 parent 7b5feb1 commit 7800baa
Showing 1 changed file with 63 additions and 15 deletions.
78 changes: 63 additions & 15 deletions R/data.table.R
Original file line number Diff line number Diff line change
Expand Up @@ -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<mn))
for (i in which(n<mn)) {
if (!is.null(x[[i]])) {# avoids warning when a list element is NULL
# Implementing FR #4813 - recycle with warning when nr %% nrows[i] != 0L
if (mn %% n[i] != 0)
warning("Item ", i, " is of size ", n[i], " but maximum size is ", mn, " (recycled leaving a remainder of ", mn%%n[i], " items)")
x[[i]] = rep(x[[i]], length.out=mn)

## Implementing #833
dims <- vapply(x, function(xi) length(dim(xi)), 0)
## If any element has dim, then convert to data.table using rbind/cbind
## For consistency with as.data.frame, as.data.table should
## fail if inconsisent dimensions.
## There is no recycling allowed in this situation
## (Note that as.data.frame fails where cbind/rbind only issues warning)
if (any(dims != 0)) {
bind.using <- match.arg(bind.using)
bind.func <- match.fun(bind.using)

x <- copy(x)

## Before checking nrows/ncols, Arrays must be converted to matrices
## Accomplished by modifying the 'dim' attribute
if (any(dims > 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<mn))
for (i in which(n<mn)) {
if (!is.null(x[[i]])) {# avoids warning when a list element is NULL
# Implementing FR #4813 - recycle with warning when nr %% nrows[i] != 0L
if (mn %% n[i] != 0)
warning("Item ", i, " is of size ", n[i], " but maximum size is ", mn, " (recycled leaving a remainder of ", mn%%n[i], " items)")
x[[i]] = rep(x[[i]], length.out=mn)
}
}

if (is.null(names(x)))
setattr(x,"names",paste("V",seq_len(length(x)),sep=""))
setattr(x,"row.names",.set_row_names(max(n)))
setattr(x,"class",c("data.table","data.frame"))
alloc.col(x)
}
if (is.null(names(x))) setattr(x,"names",paste("V",seq_len(length(x)),sep=""))
setattr(x,"row.names",.set_row_names(max(n)))
setattr(x,"class",c("data.table","data.frame"))
alloc.col(x)
}

as.data.table.data.table = function(x, keep.rownames=FALSE) return(x)
Expand Down

0 comments on commit 7800baa

Please sign in to comment.