Visitar URL original
Migration to Pandas 3.0 · Issue #3362 · DeepLabCut/DeepLabCut · GitHub
Skip to content

Migration to Pandas 3.0 #3362

Open
Open

Description

@deruyter92

Tracking issue for migration to Pandas 3.0

Pandas released version 3.0 in Jan 2026 which introduces breaking changes for our codebase. It would be useful to address the places where it currently breaks, so we can remove the upperbound version we introduced in #3186. Even if we eventually drop pandas altogether this is probably a worthwhile effort.

Migration is prepared in separate PRs and will require pre-emptive regression testing before final removal of the upperbound.
Some examples of the required changes are listed here. For a full overview see the Pandas migration guide.

Copy on write (CoW)
This is arguably one of the most important ones as it removes the possibility of mutating parent dataframes via assignments in their subset views (e.g. chained .loc[..] assignment), for more predictable behavior. The worst-case to avoid is that data manipulations in our codebase might silently take no effect on the intended parent DataFrame.

String extension
Pandas 3.0 introduces a new default str datatype that is more efficient than object. Unfortunately this default datatype does not work well with our multi-index HDFs: by default the index/column levels become the new str extension dtype instead of object and PyTables (to_hdf) cannot serialize a MultiIndex whose levels use extension dtypes:

NotImplementedError: Saving a MultiIndex with an extension dtype is not supported.

This would require us to change all dataframes back to object before saving.

PRs

Activity

  1. self-assigned this
    on Jun 10, 2026
  2. added theissue type on Jun 10, 2026
  3. added
    dependenciesPull requests that update a dependency file
    packagingPRs that modify metadata, dependency declarations, etc used to build and install the project.
    on Jun 10, 2026
  4. added this to the Pandas 3.0 upgrade milestone on Jun 26, 2026
  5. AxelNoun commented on Oct 7, 2026

    @AxelNoun
    Contributor

    Notes on the pandas 3 migration, checked on 2026-10-07 against dev at 350917d.

    Canary cell pandas>=3 (ubuntu, Python 3.12, pandas 3.0.6). The most recent run of this cell (job on #3544, against dev, 2026-10-06) reports 5 failed, 3587 passed, 41 skipped, 6 xfailed, and the functional scripts pass. The three runs of 2026-10-01 on #3540, #3541 and #3542 (against main) show the same five failures. All five are in tests/utils/test_pandas_cow.py, which @deruyter92 added to #3445. Each of these tests sets DLC_PANDAS_FUTURE=1, so the version gate in deeplabcut/utils/pandas_future_mode.py, which by design accepts only pandas 2.3.x, raises:

    RuntimeError: pandas future mode requires pandas 2.3.x, got 3.0.6
    

    These failures therefore come from the test setup, not from DeepLabCut behaviour under pandas 3.

    Two call sites that the canary does not exercise. No test under tests/ references either module, and neither functional script uses them. I ran the exact source of the code involved (_format_gt_data and its helpers; filter_low_prob and the groupby statement), extracted from dev at 350917d, on synthetic DLC-style frames:

    • deeplabcut/gui/tracklet_toolbox.py:886, df.groupby(level="bodyparts", axis=1, group_keys=False).apply(filter_low_prob, prob=pcutoff): under pandas 3.0.6, it raises TypeError: DataFrame.groupby() got an unexpected keyword argument 'axis'; under pandas 2.3.3, it runs with a FutureWarning.
    • deeplabcut/benchmark/metrics.py:38, df.stack("individuals", dropna=False) in _format_gt_data: under pandas 3.0.6, it raises ValueError: dropna must be unspecified as the new implementation does not introduce rows of NA values; under pandas 2.3.3, it runs with a FutureWarning.

    Two observations that may be relevant to the fix:

    • metrics.py: with stack("individuals", future_stack=True) instead, _format_gt_data runs on both versions, and under 2.3.3 it returns the same arrays and metadata as the current code on a synthetic two-animal file with missing values. This is a single synthetic case, not a proof of equivalence.
    • tracklet_toolbox.py: under 2.3.3, each bodyparts group contains the columns of every individual, and cols.iloc[:, 2] is the likelihood of the first individual only. On a synthetic two-animal frame, a low likelihood for animal1 also sets the keypoint of animal2 to NaN, whereas a low-likelihood keypoint of animal2 is kept. A port that preserves the grouping and iloc[:, 2] would preserve this behaviour; masking per individual would change what is exported. Is the current behaviour intended?

    HDF and the str dtype (issue description). On pandas 3.0.6 with PyTables 3.11.1, synthetic DLC-style frames whose four column levels have the new str dtype round-trip through to_hdf/read_hdf under a strict assert_frame_equal (dtypes included), with either the python or the pyarrow string storage. This holds in fixed format with a RangeIndex or a labeled-data/video/image MultiIndex as row index, and in table format with a RangeIndex. With a row MultiIndex, table format already fails on pandas 2.3.3, with a ValueError about data_columns. The NotImplementedError quoted in the description is raised by pandas 2.3.3 in fixed format once future.infer_string is enabled, as pandas_future_mode.py does; in pandas 3.0.0 and 3.0.6, pandas/io/pytables.py skips this check for StringDtype levels. For these layouts, the conversion back to object before saving may therefore not be needed under pandas 3; I have not tested this on real project files.

    @deruyter92, as the assignee of this issue (the #3362 TODOs in the code also carry your handle): are these sites already covered in your migration work? If not, would separate small PRs against dev be useful, first for test_pandas_cow.py under pandas >= 3, then for each call site with a regression test?

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

Metadata

Metadata

Assignees

Labels

dependenciesPull requests that update a dependency filepackagingPRs that modify metadata, dependency declarations, etc used to build and install the project.

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions