Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@

4. `sum(<int64 column>)` by group is correct with missing entries and GForce activated ([#7571](https://github.com/Rdatatable/data.table/issues/7571)). Thanks to @rweberc for the report and @manmita for the fix. The issue was caused by a faulty early `break` that spilled between groups, and resulted in silently incorrect results!

5. `fread(text=)` could segfault when reading text input ending with a `\x1a` (ASCII SUB) character after a long line, [#7407](https://github.com/Rdatatable/data.table/issues/7407) which is solved by adding check for eof. Thanks @aitap for the report and @manmita for the fix.
5. `fread(text=)` could segfault when reading text input ending with a `\x1a` (ASCII SUB) character after a long line, [#7407](https://github.com/Rdatatable/data.table/issues/7407) which is solved by adding check for eof. Thanks @aitap for the report and @manmita for the fix.

6. `rowwiseDT()` now provides a helpful error message when a complex object that is not a list (e.g., a function) is provided as a cell value, instructing the user to wrap it in `list()`, [#7219](https://github.com/Rdatatable/data.table/issues/7219). Thanks @kylebutts for the report and @venom1204 for the fix.

### Notes

Expand Down
8 changes: 8 additions & 0 deletions R/rowwiseDT.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ rowwiseDT = function(...) {
nrows = length(body) %/% ncols
if (length(body) != nrows * ncols)
stopf("There are %d columns but the number of cells is %d, which is not an integer multiple of the columns", ncols, length(body))
is_problematic = vapply_1b(body, function(v) !(is.atomic(v) || is.null(v) || typeof(v) == "list"))
if (any(is_problematic)) {
idx = which(is_problematic)[1L]
col_idx = (idx - 1L) %% ncols + 1L
col_name = header[col_idx]
obj_type = class1(body[[idx]])
stopf("Column '%s' is type '%s'. Non-atomic, non-list objects must be wrapped in list(), e.g., list(f) instead of f", col_name, obj_type)
}
# make all the non-scalar elements to a list
needs_list = lengths(body) != 1L
body[needs_list] = lapply(body[needs_list], list)
Expand Down
13 changes: 13 additions & 0 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -22035,3 +22035,16 @@ if (test_bit64) local({
# 7407 Test for fread() handling \x1A (ASCII SUB) at end of input
txt = paste0("foo\n", strrep("a", 4096 * 100), "\x1A")
test(2359.1, nchar(fread(txt)$foo), 409600L)

# rowwiseDT() valid and invalid handling of complex objects #7219
test(2360.1, rowwiseDT(x =, y =, 1, 2, 3, 4), data.table(x = c(1, 3), y = c(2, 4)))
test(2360.2, rowwiseDT(x =, func =,
1, list(\(x) x + 1),
2, list(function(z) z * 2)),
data.table(x = c(1, 2), func = list(\(x) x + 1, function(z) z * 2)))
test(2360.3, rowwiseDT(x =, func =, 1, \(x) x + 1),
error = "Column 'func' is type 'function'. Non-atomic, non-list objects must be wrapped in list\\(\\)")
test(2360.4, rowwiseDT(x =, expr =, 1, quote(a + b)),
error = "Column 'expr' is type 'call'. Non-atomic, non-list objects must be wrapped in list\\(\\)")
test(2360.5, rowwiseDT(x =, plist =, 1, as.pairlist(list(123))),
error = "Column 'plist' is type 'pairlist'. Non-atomic, non-list objects must be wrapped in list\\(\\)")
Loading