Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cbind fails if input is a 0-column data frame. #3334

Closed
kzenstratus opened this issue Jan 30, 2019 · 1 comment · Fixed by #3748
Closed

cbind fails if input is a 0-column data frame. #3334

kzenstratus opened this issue Jan 30, 2019 · 1 comment · Fixed by #3748
Milestone

Comments

@kzenstratus
Copy link

@kzenstratus kzenstratus commented Jan 30, 2019

Credit goes to @austin3dickey for diagnosing this and @hcui10 for digging further.

When one of the arguments is a 0-column data frame, the overloaded function, cbind() fails with
Error in data.table::data.table(...) : Item 2 has no length. Provide at least one item (such as NA, NA_integer_ etc) to be repeated to match the 5 rows in the longest column. Or, all columns can be 0 length, for insert()ing rows into.

Reproducible Example

> dt1 <- data.table::data.table(a = 1:5, b = 6:10)
> df1 <- as.data.frame(dt)
> df2 <- data.frame()[1:5, ]
> dt1
   a  b
1: 1  6
2: 2  7
3: 3  8
4: 4  9
5: 5 10
> df1
  a  b
1 1  6
2 2  7
3 3  8
4 4  9
5 5 10
> df2
data frame with 0 columns and 5 rows
> cbind(df1, df2)
     a  b
NA   1  6
NA.1 2  7
NA.2 3  8
NA.3 4  9
NA.4 5 10
> cbind(dt1, df2)

Error in data.table::data.table(...) : 
  Item 2 has no length. Provide at least one item (such as NA, NA_integer_ etc) to be repeated to match the 5 rows in the longest column. Or, all columns can be 0 length, for insert()ing rows into.

Root Cause Diagnosis

This seems to occur when cbind.data.frame converts a data.frame into a data.table.

# line 29-33 in data.table::data.table
else if (is.matrix(xi) || is.data.frame(xi)) {
            xi = as.data.table(xi, keep.rownames = keep.rownames)
            x[[i]] = xi
            numcols[i] = length(xi)
        }

This causes the number of rows to change.

> df <- data.frame()[1:5, ]
data frame with 0 columns and 5 rows
> data.table::data.table(df)
Empty data.table (0 rows) of 1 col: df

Which fails below since the number of rows is now 0.

# line 72-75 in data.table::data.table
if (nrows[i] == 0L) 
            stop("Item ", i, " has no length. Provide at least one item (such as NA, NA_integer_ etc) to be repeated to match the ", 
                nr, " row", if (nr > 1L) 
                  "s", " in the longest column. Or, all columns can be 0 length, for insert()ing rows into.")

Original Point of Failure

This was originally discovered when attempting to run the following.

library(ggfortify)
library(ggplot2)
# Works!
autoplot(stats::prcomp(iris[, c(1,2,3,4)]), data = iris, colour = 'Species')

# Doesn't work
iris <- data.table::as.data.table(iris)
autoplot(stats::prcomp(iris[, c(1,2,3,4)]), data = iris, colour = 'Species')

# Works Again!
iris <- as.data.frame(iris)
> autoplot(stats::prcomp(iris[, c(1,2,3,4)]), data = iris, colour = 'Species')
@jangorecki
Copy link
Member

@jangorecki jangorecki commented Jan 30, 2019

This could be simplified to

library(data.table)
data.table(data.table(a=1), data.table())
#Error in data.table::data.table(...) : 
#  Item 2 has no length. Provide at least one item (such as NA, NA_integer_ etc) to be repeated to match the 1 row in the longest column. Or, all columns can be 0 length, for insert()ing rows into.

in data.table we do not allow to have non-0 rows for 0 columns, but of course such usage could be handled nicely.

@jangorecki jangorecki changed the title [BUG] cbind fails if input is a 0-column data frame. cbind fails if input is a 0-column data frame. Mar 6, 2019
@mattdowle mattdowle added this to the 1.12.4 milestone Aug 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants