Skip to content

Recognize named-aggregation lambdas as scans in GroupBy - #23300

Merged
rapids-bot[bot] merged 7 commits into
NVIDIA:release/26.08from
galipremsagar:groupby-lambda-scan-detection
Jul 21, 2026
Merged

Recognize named-aggregation lambdas as scans in GroupBy#23300
rapids-bot[bot] merged 7 commits into
NVIDIA:release/26.08from
galipremsagar:groupby-lambda-scan-detection

Conversation

@galipremsagar

Copy link
Copy Markdown
Contributor

Description

A lambda like lambda x: x.cumsum() resolves through make_aggregation's op(Aggregation) protocol, where Aggregation.cumsum is an alias of sum: the scan/reduction distinction exists only in the aggregation name. _is_all_scan_aggregate identified scans via __name__ ("<lambda>"), so such transforms silently computed group totals and broadcast them instead of scanning. Probe callables with a name-recording stand-in mirroring the op(Aggregation) protocol; true UDFs raise inside the probe and fall back to __name__ as before.

Fixes 2 pandas-tests (test_cython_transform_series[cumsum/cumprod-<lambda>]); their xfail entries are removed.

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@galipremsagar
galipremsagar requested a review from a team as a code owner July 16, 2026 18:47
@galipremsagar galipremsagar added bug Something isn't working Python Affects Python cuDF API. non-breaking Non-breaking change cudf.pandas Issues specific to cudf.pandas labels Jul 16, 2026
@copy-pr-bot

copy-pr-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@GPUtester GPUtester moved this to In Progress in cuDF Python Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 04e4d80c-5e69-49ec-b604-be6605870e76

📥 Commits

Reviewing files that changed from the base of the PR and between e514d19 and 259812d.

📒 Files selected for processing (3)
  • python/cudf/cudf/core/groupby/groupby.py
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
  • python/cudf/cudf/tests/groupby/test_transform.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • python/cudf/cudf/tests/groupby/test_transform.py
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
  • python/cudf/cudf/core/groupby/groupby.py

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Fixed grouped transform for lambda-based cumulative operations (e.g., cumsum/cumprod) to use per-group cumulative scans instead of broadcasting group totals.
    • Improved aggregation classification for callables to better distinguish scan-style vs reduction-style behavior.
  • Tests
    • Added a regression test for groupby(...)[column].transform(lambda x: x.cumsum()), verifying per-group cumulative behavior.
    • Refined internal test failure reporting for specific groupby transform scenarios.

Walkthrough

Changes

Groupby scan lambda handling

Layer / File(s) Summary
Callable aggregation name resolution
python/cudf/cudf/core/groupby/groupby.py
Callable aggregations are probed to resolve chained names such as cumsum before scan-versus-reduction classification.
Transform regression coverage and failure mappings
python/cudf/cudf/tests/groupby/test_transform.py, python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
Adds a Pandas comparison test for lambda-based cumulative transforms, updates the copyright year, and removes obsolete failure-reason entries.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: tomaugspurger, bdice, mroeschke

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title concisely states the main change: treating named-aggregation lambdas as scans in GroupBy.
Description check ✅ Passed The description matches the code changes and test updates, explaining the scan-detection fix and removed xfails.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
python/cudf/cudf/core/groupby/groupby.py (1)

218-239: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Cache resolved callable names before computing both predicates.

get_name executes the callable probe, but _is_all_scan_aggregate calls it separately in all() and any(). Materialize the flattened resolved names once, then derive both predicates from that list; ideally reuse the aggregation resolution already performed by make_aggregation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudf/cudf/core/groupby/groupby.py` around lines 218 - 239, Update the
groupby aggregation-name resolution around get_name and _is_all_scan_aggregate
to materialize each flattened callable’s resolved name once, then compute both
all-scan and any-scan predicates from that cached list. Reuse the names produced
during make_aggregation when available, avoiding repeated callable probes while
preserving existing handling for non-callables and true UDFs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@python/cudf/cudf/tests/groupby/test_transform.py`:
- Around line 82-91: Expand test_transform_scan_lambda to parameterize both
cumsum and cumprod across empty, all-null, single-element, and mixed-type
inputs, while retaining expected pandas-versus-cuDF comparisons for each case.
Add the repository-required unit benchmark covering this scan-lambda regression.

---

Nitpick comments:
In `@python/cudf/cudf/core/groupby/groupby.py`:
- Around line 218-239: Update the groupby aggregation-name resolution around
get_name and _is_all_scan_aggregate to materialize each flattened callable’s
resolved name once, then compute both all-scan and any-scan predicates from that
cached list. Reuse the names produced during make_aggregation when available,
avoiding repeated callable probes while preserving existing handling for
non-callables and true UDFs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6c499992-a1df-4636-84be-e14d105a6a93

📥 Commits

Reviewing files that changed from the base of the PR and between 9d9fec8 and 42efad0.

📒 Files selected for processing (3)
  • python/cudf/cudf/core/groupby/groupby.py
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
  • python/cudf/cudf/tests/groupby/test_transform.py
💤 Files with no reviewable changes (1)
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py

Comment on lines +82 to +91
def test_transform_scan_lambda():
# a named-aggregation lambda resolving to a scan must scan per group,
# not broadcast the group total
pdf = pd.DataFrame({"key": [0, 0, 1, 1], "val": [1.0, 2.0, 3.0, 4.0]})
gdf = cudf.DataFrame(pdf)

expect = pdf.groupby("key")["val"].transform(lambda x: x.cumsum())
got = gdf.groupby("key")["val"].transform(lambda x: x.cumsum())

assert_eq(expect, got)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Expand scan-lambda regression coverage.

This test covers only cumsum on a simple non-null float input. Parameterize the regression for cumsum and cumprod, and add empty, all-null, single-element, and mixed-type cases. Add a unit benchmark for this bug fix as required by the repository guidelines.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudf/cudf/tests/groupby/test_transform.py` around lines 82 - 91,
Expand test_transform_scan_lambda to parameterize both cumsum and cumprod across
empty, all-null, single-element, and mixed-type inputs, while retaining expected
pandas-versus-cuDF comparisons for each case. Add the repository-required unit
benchmark covering this scan-lambda regression.

Source: Coding guidelines

A lambda like ``lambda x: x.cumsum()`` resolves through
make_aggregation's op(Aggregation) protocol, where Aggregation.cumsum
is an alias of sum: the scan/reduction distinction exists only in the
aggregation name. _is_all_scan_aggregate identified scans via
``__name__`` ("<lambda>"), so such transforms silently computed group
totals and broadcast them instead of scanning. Probe callables with a
name-recording stand-in mirroring the op(Aggregation) protocol; true
UDFs raise inside the probe and fall back to ``__name__`` as before.
@galipremsagar
galipremsagar force-pushed the groupby-lambda-scan-detection branch from 42efad0 to ac77cac Compare July 17, 2026 01:41
@galipremsagar
galipremsagar changed the base branch from main to release/26.08 July 17, 2026 01:41
@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test 76649b0

@galipremsagar
galipremsagar requested a review from mroeschke July 17, 2026 13:51
@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test 126a93e

@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test d1e8eb3

@vyasr vyasr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Wow this is a convoluted fix :( I really wish we didn't have to support agg machinery through callables the way that we do.

@galipremsagar galipremsagar added the 5 - Ready to Merge Testing and reviews complete, ready to merge label Jul 20, 2026
…mbda-scan-detection

# Conflicts:
#	python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test e514d19

…mbda-scan-detection

# Conflicts:
#	python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
#	python/cudf/cudf/tests/groupby/test_transform.py
@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test 259812d

@galipremsagar

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot
rapids-bot Bot merged commit c907bca into NVIDIA:release/26.08 Jul 21, 2026
126 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in cuDF Python Jul 21, 2026
davidwendt pushed a commit to wjxiz1992/cudf that referenced this pull request Jul 21, 2026
A lambda like `lambda x: x.cumsum()` resolves through `make_aggregation`'s `op(Aggregation)` protocol, where `Aggregation.cumsum` is an alias of `sum`: the scan/reduction distinction exists only in the aggregation name. `_is_all_scan_aggregate` identified scans via `__name__` (`"<lambda>"`), so such transforms silently computed group totals and broadcast them instead of scanning. Probe callables with a name-recording stand-in mirroring the `op(Aggregation)` protocol; true UDFs raise inside the probe and fall back to `__name__` as before.

Fixes 2 pandas-tests (`test_cython_transform_series[cumsum/cumprod-<lambda>]`); their xfail entries are removed.

Authors:
  - GALI PREM SAGAR (https://github.com/galipremsagar)

Approvers:
  - Vyas Ramasubramani (https://github.com/vyasr)

URL: NVIDIA#23300
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

5 - Ready to Merge Testing and reviews complete, ready to merge bug Something isn't working cudf.pandas Issues specific to cudf.pandas non-breaking Non-breaking change Python Affects Python cuDF API.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants