Skip to content

Refactor groupby grouping and Python ordering - #24562

Open
PointKernel wants to merge 12 commits into
NVIDIA:mainfrom
PointKernel:refactor/groupby-grouping-preparation
Open

PointKernel wants to merge 12 commits into
NVIDIA:mainfrom
PointKernel:refactor/groupby-grouping-preparation

Conversation

@PointKernel

@PointKernel PointKernel commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Description

This PR separates HashCSR key grouping from aggregation and reuses group ordering and row mappings in cuDF Python and Polars. It preserves pandas-compatible group order and correctly restores row positions after apply and window operations.

Split out from #24251.

Checklist

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

@copy-pr-bot

copy-pr-bot Bot commented Oct 12, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions github-actions Bot added libcudf Affects libcudf (C++/CUDA) code. Python Affects Python cuDF API. CMake CMake build issue cudf.pandas Issues specific to cudf.pandas cudf-polars Issues specific to cudf-polars labels Oct 12, 2026
@PointKernel PointKernel added non-breaking Non-breaking change improvement Improvement / enhancement to an existing function labels Oct 12, 2026
@PointKernel

Copy link
Copy Markdown
Member Author

/ok to test

@PointKernel
PointKernel marked this pull request as ready for review October 12, 2026 23:46
@PointKernel
PointKernel requested review from a team as code owners October 12, 2026 23:46
@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Review in 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: Repository: NVIDIA/cudf/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: d0d6168f-f075-4d91-89fa-08b97b1bcc62
📥 Commits

Reviewing files that changed from the base of the PR and between 09e2c41 and 75027e1.

📒 Files selected for processing: 3
  • cpp/src/groupby/hash/group_keys.cu
  • cpp/src/groupby/hash/group_keys.hpp
  • python/cudf/cudf/core/groupby/groupby.py

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 9 remain after this review.

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • GroupBy operations with sort=False now consistently preserve first-appearance group order across iteration, aggregation, apply, row selection, and scan results.
    • Pandas-compatible grouping now applies the expected ordering to reduction results, including when sorting is disabled.
    • Grouped rolling operations now retain input row order when reordering results.
    • Hash-based grouping now handles aggregation requests and includes or excludes null keys according to the selected policy.

The PR separates C++ hash key grouping from aggregation execution. It centralizes cuDF Python group ordering and changes Polars rolling expressions to use row IDs returned by the grouper when restoring input order.

Changes: C++ Hash Groupby

Layer / File(s) Summary
Key grouping contract and implementation
cpp/src/groupby/hash/group_keys.hpp, cpp/src/groupby/hash/group_keys.cu
Adds a grouped-key result and a table-based grouping function. The function handles null-key policy and prepares key comparison and hashing.
Aggregation execution and entry-point wiring
cpp/src/groupby/hash/compute_groupby.hpp, cpp/src/groupby/hash/compute_groupby.cpp, cpp/src/groupby/hash/groupby.cu, cpp/CMakeLists.txt
Moves aggregation extraction, execution, caching, and compound-aggregation finalization into compute_groupby. The groupby entry point calls it directly, and CMake compiles its .cpp source.

Group Ordering

Layer / File(s) Summary
Group order selection and caching
python/cudf/cudf/core/groupby/groupby.py
Adds ordering controls and caches for group offsets and row permutations. Groups can follow key order or first input-row position.
Ordered groupby operations and validation
python/cudf/cudf/core/groupby/groupby.py, python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py, python/cudf/cudf/tests/groupby/*
Routes aggregation, iteration, head and tail, apply, and scan ordering through the ordering controls. Updates groupby tests and removes two expected-failure entries.
Polars rolling row-order restoration
python/cudf_polars/cudf_polars/dsl/expressions/rolling.py
Uses row IDs returned by the grouper when restoring input order without an explicit order index. Updates the rolling, rank, and fill-null call sites.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to 75027

This change restructures how groupby builds key groups and how group order is preserved in Python and Polars. It is intended to keep pandas-compatible ordering. The review found no concrete defect in the supplied changes, so the change looks ready to merge after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 46.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 28 functions across 10 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main changes: refactoring groupby grouping and Python ordering.
Description check Passed The description directly explains the separation of HashCSR grouping from aggregation and the reuse of ordering and row mappings in cuDF Python and Polars.
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 a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@wence- wence- 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.

Approving python changes.

Comment thread cpp/src/groupby/hash/group_keys.hpp Outdated
Comment thread cpp/src/groupby/hash/compute_groupby.cpp Outdated

@mhaseeb123 mhaseeb123 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.

One nit

else []
)
positions = value_columns.pop() if need_positions else None
if not order_groups or len(offsets) <= 2:

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.

nit: get_groups already returns sorted groups with sort=True, so we can return early here. Can also drop the sort=True branch below.

Suggested change
if not order_groups or len(offsets) <= 2:
if not order_groups or self._sort or len(offsets) <= 2:

auto const temporary_resources = mr.as_temporary();

[[maybe_unused]] auto [row_bitmask_data, row_bitmask] =
auto const num_rows = keys.num_rows();

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.

nit: Since need_grouped_rows requires group offsets

Suggested change
auto const num_rows = keys.num_rows();
CUDF_EXPECTS(need_group_offsets || !need_grouped_rows,
"Grouped rows require group offsets",
std::invalid_argument);
auto const num_rows = keys.num_rows();

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

Labels

CMake CMake build issue cudf.pandas Issues specific to cudf.pandas cudf-polars Issues specific to cudf-polars improvement Improvement / enhancement to an existing function libcudf Affects libcudf (C++/CUDA) code. non-breaking Non-breaking change Python Affects Python cuDF API.

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants