diff --git a/NEWS.md b/NEWS.md index ad673a4417..0a9e8f0745 100644 --- a/NEWS.md +++ b/NEWS.md @@ -78,6 +78,8 @@ 11. Assigning a set of 2 or more all-NA values to a factor column could segfault, [#4824](https://github.com/Rdatatable/data.table/issues/4824). Thanks to @clerousset for reporting and @shrektan for fixing. +12. `as.data.table(table(NULL))` now returns `data.table(NULL)` rather than error `attempt to set an attribute on NULL`, [#4179](https://github.com/Rdatatable/data.table/issues/4179). The result differs slightly to `as.data.frame(table(NULL))` (0-row, 1-column) because 0-column works better with other `data.table` functions like `rbindlist()`. Thanks to Michael Chirico for the report and fix. + ## NOTES 1. New feature 29 in v1.12.4 (Oct 2019) introduced zero-copy coercion. Our thinking is that requiring you to get the type right in the case of `0` (type double) vs `0L` (type integer) is too inconvenient for you the user. So such coercions happen in `data.table` automatically without warning. Thanks to zero-copy coercion there is no speed penalty, even when calling `set()` many times in a loop, so there's no speed penalty to warn you about either. However, we believe that assigning a character value such as `"2"` into an integer column is more likely to be a user mistake that you would like to be warned about. The type difference (character vs integer) may be the only clue that you have selected the wrong column, or typed the wrong variable to be assigned to that column. For this reason we view character to numeric-like coercion differently and will warn about it. If it is correct, then the warning is intended to nudge you to wrap the RHS with `as.()` so that it is clear to readers of your code that a coercion from character to that type is intended. For example : diff --git a/R/as.data.table.R b/R/as.data.table.R index d4d234cb53..9509774075 100644 --- a/R/as.data.table.R +++ b/R/as.data.table.R @@ -33,6 +33,8 @@ as.data.table.Date = as.data.table.ITime = function(x, keep.rownames=FALSE, key= # as.data.table.table - FR #361 as.data.table.table = function(x, keep.rownames=FALSE, key=NULL, ...) { + # prevent #4179 & just cut out here + if (any(dim(x) == 0L)) return(null.data.table()) # Fix for bug #43 - order of columns are different when doing as.data.table(with(DT, table(x, y))) val = rev(dimnames(provideDimnames(x))) if (is.null(names(val)) || !any(nzchar(names(val)))) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 378d2dc93f..43cf3d87ca 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -16907,7 +16907,6 @@ test(2132.2, fifelse(TRUE, 1, s2), error = "S4 class objects (except nanot test(2132.3, fcase(TRUE, s1, FALSE, s2), error = "S4 class objects (except nanotime) are not supported. Please see") test(2132.4, fcase(FALSE, 1, TRUE, s1), error = "S4 class objects (except nanotime) are not supported. Please see") rm(s1, s2, class2132) - if (test_xts) { # keep.rownames in as.data.table.xts() supports a string, #4232 xts = xts::xts(1:10, structure(1:10, class = "Date")) @@ -17419,3 +17418,6 @@ test(2179, DT$FACTOR, factor(c(NA, NA, "a"))) # deleting duplicated column name removes only first DT = data.table(a=1, b=2, a=3) test(2180, DT[, a:=NULL], data.table(b=2, a=3)) + +# as.data.table(table(NULL)) was error, #4179 +test(2181, as.data.table(table(NULL)), data.table(NULL))