Implement factorize for MultiIndex - #23139
Conversation
|
/okay to test ca37851 |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR adds ChangesMultiIndex Factorize Support
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
/okay to test bf33cd4 |
|
/merge |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
python/cudf/cudf/tests/general_functions/test_factorize.py (1)
108-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider adding a named empty-MultiIndex case.
The current empty test uses an unnamed
MultiIndex, so it won't catch the names-handling gap between the empty and non-empty branches of_factorize(see multiindex.py comment). Adding a variant withnames=[...]would close this coverage gap.🤖 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/general_functions/test_factorize.py` around lines 108 - 116, The empty MultiIndex factorize test only covers an unnamed case, so it misses the names-handling path difference in `_factorize`. Update `test_factorize_multiindex_empty` in `test_factorize.py` to add a named empty `MultiIndex` variant using `pd.MultiIndex.from_arrays(..., names=[...])` and assert `factorize()` preserves the expected empty result and names via `gmi[:0]`.
🤖 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/core/multiindex.py`:
- Around line 1804-1805: The empty MultiIndex path in `MultiIndex.factorize`
returns `self.copy()`, which preserves level names and makes the `uniques`
result inconsistent with the non-empty branch. Update the `len(self) == 0`
branch so the returned empty `MultiIndex` mirrors the non-empty behavior by
clearing names to `[None] * self.nlevels`, using the existing
`MultiIndex.factorize`/`self.copy()` flow as the place to apply the fix.
---
Nitpick comments:
In `@python/cudf/cudf/tests/general_functions/test_factorize.py`:
- Around line 108-116: The empty MultiIndex factorize test only covers an
unnamed case, so it misses the names-handling path difference in `_factorize`.
Update `test_factorize_multiindex_empty` in `test_factorize.py` to add a named
empty `MultiIndex` variant using `pd.MultiIndex.from_arrays(..., names=[...])`
and assert `factorize()` preserves the expected empty result and names via
`gmi[:0]`.
🪄 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: e50634f1-ff7f-4bd9-b906-358df5ce2285
📒 Files selected for processing (3)
python/cudf/cudf/core/multiindex.pypython/cudf/cudf/pandas/scripts/pandas-testing-plugin.pypython/cudf/cudf/tests/general_functions/test_factorize.py
| if len(self) == 0: | ||
| return cp.empty(0, dtype=np.intp), self.copy() |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Empty MultiIndex factorize doesn't strip level names, unlike the non-empty path.
For the non-empty path, uniques_mi.names is explicitly reset to [None] * self.nlevels to match pandas (per the comment at line 1838). But the empty branch returns self.copy(), which preserves the original names. For a named empty MultiIndex, this makes uniques inconsistent with the non-empty behavior (and, per the code's own rationale, with pandas). The current empty test doesn't catch this because it constructs an unnamed MultiIndex.
🐛 Proposed fix
if len(self) == 0:
- return cp.empty(0, dtype=np.intp), self.copy()
+ empty = self.copy()
+ empty.names = [None] * self.nlevels
+ return cp.empty(0, dtype=np.intp), empty📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if len(self) == 0: | |
| return cp.empty(0, dtype=np.intp), self.copy() | |
| if len(self) == 0: | |
| empty = self.copy() | |
| empty.names = [None] * self.nlevels | |
| return cp.empty(0, dtype=np.intp), empty |
🤖 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/multiindex.py` around lines 1804 - 1805, The empty
MultiIndex path in `MultiIndex.factorize` returns `self.copy()`, which preserves
level names and makes the `uniques` result inconsistent with the non-empty
branch. Update the `len(self) == 0` branch so the returned empty `MultiIndex`
mirrors the non-empty behavior by clearing names to `[None] * self.nlevels`,
using the existing `MultiIndex.factorize`/`self.copy()` flow as the place to
apply the fix.
# Conflicts: # python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
|
/okay to test 8b8dd84 |
|
/merge |
|
/okay to test 4d6588e |
|
/merge |
MultiIndex._factorizesofactorizeon a MultiIndex (and tuple data) returns codes and uniques across all levels, with first-appearance or lexicographic ordering persort.