Skip to content

Conversation

@venom1204
Copy link
Contributor

closes #7219

This PR enhances rowwise() to detect all non-atomic, non-list column values (e.g., language objects, expressions, pairlists, environments, S4 objects) instead of only functions. It adds a clear error message with the offending column name and type, plus guidance to wrap values in list(...) if intended. Includes updated tests for both allowed and rejected cases.

hi @tdhock @MichaelChirico @aitap can you please have a look when you got time .

thanks.

@codecov
Copy link

codecov bot commented Aug 12, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.02%. Comparing base (0912a66) to head (8f1bd4f).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #7250   +/-   ##
=======================================
  Coverage   99.02%   99.02%           
=======================================
  Files          87       87           
  Lines       16791    16798    +7     
=======================================
+ Hits        16628    16635    +7     
  Misses        163      163           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link

github-actions bot commented Aug 12, 2025

  • HEAD=issue_7219 stopped early for DT[by,verbose=TRUE] improved in #6296
    Comparison Plot

Generated via commit 1371a79

Download link for the artifact containing the test results: ↓ atime-results.zip

Task Duration
R setup and installing dependencies 5 minutes and 16 seconds
Installing different package versions 11 minutes and 17 seconds
Running and plotting the test cases 4 minutes and 8 seconds

R/rowwiseDT.R Outdated
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))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please undo addition of empty lines

Copy link
Member

@tdhock tdhock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please fix

@venom1204 venom1204 requested a review from tdhock August 15, 2025 07:06
@venom1204
Copy link
Contributor Author

hi @tdhock I did the modifications can you please have a look when you got time.
thanks

R/rowwiseDT.R Outdated
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(
body,
function(v) !is.atomic(v) && !is.null(v) && typeof(v) != "list",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this check really what @aitap wrote about catering for that is.atomic(NULL)=TRUE on older R versions?

it should also be faster to check !(is.atomic(v) || is.null(v) || typeof(v) == "list")

Note that we have our internal versions of vapply e.g. vapply_1b

@venom1204 venom1204 requested a review from ben-schwen August 25, 2025 10:01
R/rowwiseDT.R Outdated
first_problem_idx = which(is_problematic)[1L]
col_idx = (first_problem_idx - 1L) %% ncols + 1L
col_name = header[col_idx]
obj_type = typeof(body[[first_problem_idx]])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if typeof is the right choice here. For the problem raised in #7219 class would be a better choice since class would be "function" but typeof would be still "closure".

R/rowwiseDT.R Outdated
col_name = header[col_idx]
obj_type = typeof(body[[first_problem_idx]])
stopf(
"In column '%s', received an object of type '%s'.\nComplex objects (like functions, models, etc.) must be wrapped in list() to be stored in a data.table column.\nPlease use `list(...)` for this value.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really true? Many models are indeed lists, e.g. lm(mpg~., data=mtcars).

Other thing on top of my head would be expressions which we do not fully support. Storing environments into a data.table seems uncommon to me.

Copy link
Member

@ben-schwen ben-schwen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also still miss a NEWS item!

@venom1204 venom1204 requested a review from ben-schwen August 30, 2025 11:43
R/rowwiseDT.R Outdated
col_name = header[col_idx]
obj_type = class1(body[[first_problem_idx]])
stopf(
"In column '%s', received an object of type '%s'.\nComplex objects (like functions, formulas, or calls) must be wrapped in list() to be stored in a data.table column.\nPlease use `list(...)` for this value.",
Copy link
Member

@ben-schwen ben-schwen Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indent is off, see e.g.

> rowwiseDT(x =, func =, 1, \(x) x + 1)
Error in rowwiseDT(x = , func = , 1, function(x) x + 1) : 
  In column 'func', received an object of type 'function'.
Complex objects (like functions, formulas, or calls) must be wrapped in list() to be stored in a data.table column.
Please use `list(...)` for this value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also something more in the direction of

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)

R/rowwiseDT.R Outdated
Comment on lines 21 to 24
first_problem_idx = which(is_problematic)[1L]
col_idx = (first_problem_idx - 1L) %% ncols + 1L
col_name = header[col_idx]
obj_type = class1(body[[first_problem_idx]])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
first_problem_idx = which(is_problematic)[1L]
col_idx = (first_problem_idx - 1L) %% ncols + 1L
col_name = header[col_idx]
obj_type = class1(body[[first_problem_idx]])
idx = which(is_problematic)[1L]
col_idx = (idx - 1L) %% ncols + 1L
col_name = header[col_idx]
obj_type = class1(body[[idx]])

Would feel more consistent to our codebase/

NEWS.md Outdated
19. Ellipsis elements like `..1` are correctly excluded when searching for variables in "up-a-level" syntax inside `[`, [#5460](https://github.com/Rdatatable/data.table/issues/5460). Thanks @ggrothendieck for the report and @MichaelChirico for the fix.
20. `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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
20. `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.
20. `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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ofc, it must also be moved to the 1.18.99 NEWS section

Copy link
Member

@ben-schwen ben-schwen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late review. Some minor things, but overall close to finish.

@venom1204
Copy link
Contributor Author

Sorry for the late review. Some minor things, but overall close to finish.

hi @ben-schwen
sorry for the late replies, was engaged somewhere else .
Have a look and let me know if any changes are needed.

@ben-schwen ben-schwen merged commit fd2d84a into master Jan 11, 2026
9 of 10 checks passed
@ben-schwen ben-schwen deleted the issue_7219 branch January 11, 2026 16:18
@ben-schwen
Copy link
Member

TY. Good work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rowwiseDT with column of functions

3 participants