Skip to content

Fix cudf.pandas datetimelike plotting failures (canonical freq offsets + Period/offset pickling) - #23054

Merged
rapids-bot[bot] merged 8 commits into
NVIDIA:mainfrom
galipremsagar:plotting_freq
Jul 8, 2026
Merged

Fix cudf.pandas datetimelike plotting failures (canonical freq offsets + Period/offset pickling)#23054
rapids-bot[bot] merged 8 commits into
NVIDIA:mainfrom
galipremsagar:plotting_freq

Conversation

@galipremsagar

@galipremsagar galipremsagar commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes failures in tests/plotting/test_datetimelike.py under cudf.pandas (14 of the 21 prior failures). Two root causes:

1. DatetimeIndex.freq / inferred_freq returned cudf's internal DateOffset

The public freq/inferred_freq returned a cudf.DateOffset (e.g. <DateOffset: days=1>) rather than the canonical pandas offset (<Day>, <Minute>, ...). pandas plotting APIs reject this (PeriodDtype(freq) raised TypeError: PeriodDtype argument should be string or BaseOffset, got DateOffset) and freq comparisons failed.

These now return the canonical pandas offset via _maybe_as_fast_pandas_offset(). The internal _freq keeps the cudf DateOffset for serialization/arithmetic; inferred_freq is split into a private _inferred_freq (cudf offsets, used to populate _freq) and the public inferred_freq (pandas offset). Internal callers in series.py/dataframe.py and DatetimeIndex.__init__/serialize were updated to use _freq/_inferred_freq accordingly.

Fixes test_line_plot_datetime_frame[*] (5) and test_line_plot_inferred_freq[*] (3).

2. Pickling matplotlib figures containing Period / concrete offsets

Matplotlib date converters store pandas.Period x-data and concrete offsets (Day, Week, ...) as freq. The module accelerator makes the corresponding module attributes resolve to proxies, so pickle's class-identity check failed (Can't pickle <class 'pandas.Period'>: it's not the same object as pandas.Period).

Registered copyreg reducers for Period (proxy + real) and every concrete BaseOffset subclass, mirroring the existing Timestamp/DateOffset handling. Fixes test_pickle_fig[*] (6).

The now-passing entries are removed from the cudf.pandas xfail list.

Not addressed (inherent)

The remaining test_*_weekly_resampling / test_from_resampling_area_line_mixed* failures need a weekly weekday anchor (Week(weekday=4)), which cudf cannot infer (inferred_freq raises "Can't infer anchored week"); these remain xfailed. test_add_matplotlib_datetime64 is a pandas xfail (GH9053) that xpasses under cudf.pandas due to matplotlib behavior, and stays skipped.

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 June 30, 2026 23:07
@galipremsagar
galipremsagar requested review from Matt711 and vyasr June 30, 2026 23:07
@github-actions github-actions Bot added Python Affects Python cuDF API. cudf.pandas Issues specific to cudf.pandas labels Jun 30, 2026
@galipremsagar galipremsagar added bug Something isn't working non-breaking Non-breaking change labels Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 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: f407543c-005b-4837-b25f-c367ffbc22d4

📥 Commits

Reviewing files that changed from the base of the PR and between d791fe0 and fdb05e0.

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

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved DatetimeIndex frequency handling and preservation across construction, copying, slicing, to_pandas, and representation.
    • Updated frequency inference to return canonical pandas-compatible offsets, including anchored year/month cases.
    • Enhanced pickling compatibility for pandas.Period and concrete DateOffset subclasses for more reliable interoperability.
  • Tests
    • Updated expected failure reasons for datetime/timezone and datetimelike plotting and resampling scenarios.

Walkthrough

DatetimeIndex now stores and exposes canonical pandas frequency offsets through construction, validation, slicing, serialization, and pandas conversion. The pandas wrapper also adds pickle reducers for Period and DateOffset subclasses, with updated test expectations.

Changes

DatetimeIndex frequency internals

Layer / File(s) Summary
Init, validation, and public freq
python/cudf/cudf/core/index.py
DatetimeIndex.__init__ now derives missing frequency from input .freq; _validate_freq normalizes strings and offsets to pandas BaseOffset; freq returns self._freq; repr and validation errors use freqstr.
Serialization and derived frequency
python/cudf/cudf/core/index.py
serialize/deserialize preserve self._freq, copy reuses it directly, inferred_freq returns stored or canonical inferred pandas offsets, _get_slice_frequency multiplies the stored offset directly, and to_pandas assigns result.freq = self._freq.

Pandas accelerator pickling support

Layer / File(s) Summary
Period and offset reducers
python/cudf/cudf/pandas/_wrappers/pandas.py
Registers copyreg.dispatch_table reducers for Period, pd.Period, and concrete BaseOffset subclasses under pd.tseries.offsets.
Updated test failure expectations
python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
Adjusts datetime/tz expected-failure mappings and replaces plotting-period failures with resampling cases that raise a missing-freq ValueError.

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

Suggested labels: 3 - Ready for Review

Suggested reviewers: vyasr, bdice, mroeschke

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: canonical freq offsets and pickle fixes for cudf.pandas datetimelike plotting.
Description check ✅ Passed The description clearly matches the implemented changes and explains the failures addressed, remaining xfails, and test impact.
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

🤖 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/index.py`:
- Around line 3715-3723: The public freq property on Index currently returns a
pandas offset from the getter, but the setter path through _validate_freq only
accepts str or cudf.DateOffset, so assigning idx.freq back to itself can fail.
Update the freq setter/validation logic in Index so it normalizes pandas offset
objects returned by freq into the internal cudf.DateOffset representation before
storing, ensuring the getter and setter round-trip cleanly.
🪄 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: 3c3dad96-e7d3-4b3b-aa92-fac154c626f1

📥 Commits

Reviewing files that changed from the base of the PR and between bd7bb74 and 418afac.

📒 Files selected for processing (5)
  • python/cudf/cudf/core/dataframe.py
  • python/cudf/cudf/core/index.py
  • python/cudf/cudf/core/series.py
  • python/cudf/cudf/pandas/_wrappers/pandas.py
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
💤 Files with no reviewable changes (1)
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py

Comment thread python/cudf/cudf/core/index.py Outdated
@GPUtester GPUtester moved this to In Progress in cuDF Python Jul 1, 2026
Comment thread python/cudf/cudf/core/index.py Outdated
@copy-pr-bot

copy-pr-bot Bot commented Jul 7, 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.

@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test c9cd350

@galipremsagar
galipremsagar requested a review from mroeschke July 7, 2026 08:21

@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: 2

🤖 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/index.py`:
- Around line 3651-3653: The stepped-slice fast path in DatetimeIndex handling
should not multiply by _freq when _freq is None, since that can raise TypeError
for non-unit slice steps. Update the slice handling in the relevant index logic
around the slc.step fastpath to return None when _freq is missing, and only
compute slc.step * self._freq when a frequency is available so behavior matches
pandas.
- Around line 3428-3440: The freq serialization in Index.deserialize and the
matching header construction for generic pd.DateOffset currently drops
DateOffset.n and normalize because only kwds are stored, so the offset is
reconstructed with defaults. Update the freq payload handling in
cudf/core/index.py to include n and normalize alongside kwds when building
header["freq"], and in deserialize pass those values back into
pd.DateOffset(...) using the existing header["freq"] path so the original offset
is preserved.
🪄 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: 4e813cd3-2ba0-4d24-83d7-d344bcf6ecda

📥 Commits

Reviewing files that changed from the base of the PR and between 8410d2a and c9cd350.

📒 Files selected for processing (1)
  • python/cudf/cudf/core/index.py

Comment thread python/cudf/cudf/core/index.py Outdated
Comment thread python/cudf/cudf/core/index.py
Comment thread python/cudf/cudf/core/index.py Outdated
kwds[component] = c

return cudf.DateOffset(**kwds)
return cudf.DateOffset(**kwds)._maybe_as_fast_pandas_offset()

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.

Are we at a stage where we could use pd.DateOffset(**kwds) directly?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not quite — a generic pd.DateOffset(days=1) never compares equal to the fast offsets pandas infers (pd.DateOffset(days=1) != pd.offsets.Day()) and its freqstr is not parseable, which would break freq comparisons and the freq round-trip through _validate_freq/serialization. to_offset(Timedelta(...)) is not a substitute either, since it yields <24 * Hours> for a daily delta instead of <Day>. So single-unit offsets still need converting to their fast pandas equivalents via _maybe_as_fast_pandas_offset; I added a comment at the call site in d791fe0 explaining this.

@galipremsagar
galipremsagar requested a review from mroeschke July 8, 2026 06:16
@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test fdb05e0

@galipremsagar

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot
rapids-bot Bot merged commit e1d4832 into NVIDIA:main Jul 8, 2026
124 of 126 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in cuDF Python Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cudf.pandas Issues specific to cudf.pandas non-breaking Non-breaking change Python Affects Python cuDF API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants