Skip to content

[DF] Add median support for RDataFrame - #23079

Merged
vepadulano merged 1 commit into
root-project:masterfrom
ArjunXvarma:df-median
Sep 1, 2026
Merged

vepadulano merged 1 commit into
root-project:masterfrom
ArjunXvarma:df-median

Conversation

@ArjunXvarma

@ArjunXvarma ArjunXvarma commented Aug 15, 2026 •

Copy link
Copy Markdown

This Pull request:

Changes or fixes:

Adds a Median action to RDataFrame, computing the exact median of a column.

Draft - implementation is working; Google Test coverage and doxygen documentation still to come.

Implemented as a MedianHelper in ActionHelpers.hxx following the structure of MeanHelper:
values are buffered per slot in Exec (with an IsDataContainer overload for collection columns),
and Finalize merges the per-slot buffers and uses std::nth_element to select the middle
element. Even entry counts return the average of the two middle values.

Scope, per the discussion in the issue: exact mode only. GetMergeableValue is not implemented,
so distributed execution is not supported - a median cannot be merged from a summary the way
RMergeableMean merges (mean, count), so that deserves separate discussion. Memory cost is
O(N) doubles, which is inherent to an exact result.

Manually verified so far via the templated and jitted C++ paths, from Python, on RVec columns,
and with implicit multithreading enabled.

Checklist:

  • tested changes locally
  • updated the docs
  • added tests

This PR is part of #22794

@ArjunXvarma
ArjunXvarma marked this pull request as ready for review August 17, 2026 16:42
@vepadulano

Copy link
Copy Markdown
Member

Hi @ArjunXvarma ,

Thanks for your contribution! I will go ahead and approve the CI run, meanwhile I'll take a look at the changes and comment accordingly.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown

Test Results

    23 files      23 suites   3d 13h 48m 28s ⏱️
 3 860 tests  3 860 ✅ 0 💤 0 ❌
78 622 runs  78 622 ✅ 0 💤 0 ❌

Results for commit 97cca4c.

♻️ This comment has been updated with latest results.

@ArjunXvarma

Copy link
Copy Markdown
Author

Hi @vepadulano, I have rebased onto current master to pick up the recent CI changes. Could you please approve the workflow run?

@vepadulano vepadulano left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for this effort! Here are some comments from my side

Comment thread tree/dataframe/src/RDFActionHelpers.cxx Resolved
Comment thread tree/dataframe/src/RDFActionHelpers.cxx Resolved
@vepadulano

Copy link
Copy Markdown
Member

@ArjunXvarma ,

Thanks for the update! The CI seems to be green. Before proceeding with this PR, can you still consider the addition of the two tests I mentioned in my above comment?

@ArjunXvarma

Copy link
Copy Markdown
Author

Hi @vepadulano, I'm currently working on the tests, thought I'd make separate commits for the class changes and test additions for the sake of readability.

@ArjunXvarma

ArjunXvarma commented Aug 29, 2026 •

Copy link
Copy Markdown
Author

@vepadulano, I've added the tests you suggested.

  • The multithreaded test follows the GetNSlots pattern in dataframe_interface.cxx, including the R__USE_IMT guard.

  • For the non-sensible column type I followed Define_jitted_type_unknown_to_interpreter in dataframe_simple.cxx, defining a column of type RFoo (struct RFoo {}) and asserting that Median() on it throws.

I compared this against Mean on the same column: both are rejected at the Exec(unsigned int, double) overload with no conversion from RFoo to double, with identical diagnostics apart from the helper name, so I think it's safe to say that median demonstrates the same behaviour as the existing actions.

@ArjunXvarma
ArjunXvarma requested a review from vepadulano August 30, 2026 08:18
This commit introduces the Median lazy action, which computes the median of the
values in the input column.

Median always returns an RResultPtr<double> irrespective of the input column type.

If the input column is of a type which does not make sense to compute the median
on, the action will throw a std::runtime_error during execution when the input
value is tried to be coerced into a double.

The current implementation works for local RDataFrame in single- and
multi-threaded mode. It stores all column values in a buffer and computes the
exact median at the end of processing.

@vepadulano vepadulano left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for the nice work @ArjunXvarma !

I have rebased your branch squashing all commit history and adding a commit description of the feature introduced.

No further action is required on your side, I will merge this PR once the tests pass.

@vepadulano
vepadulano merged commit 63a0e5c into root-project:master Sep 1, 2026
53 of 60 checks passed
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.

2 participants