---
title: "pandas Breaking Changes on PyPI | Since.dev"
description: "What each pandas release removed, renamed or changed: 2,946 breaking changes in 12 versions on PyPI, each with its source."
canonical_url: https://since.dev/packages/pypi/pandas
last_updated: 2026-11-11
---

# pandas breaking changes

Every breaking API change we have recorded in pandas on PyPI: 2,946 breaking changes in 12 versions. Below are its newest 6 versions, removals and renames first, each with its source.

Newest change November 11, 2026

## 3.1.1

5 breaking changes, first published November 11, 2026.

- **Signature changed** `pandas.tests.indexes.datetimes.methods.test_tz_localize.test_dti_tz_localize_nonexistent_shift_past_last_transition`  

Was def test_dti_tz_localize_nonexistent_shift_past_last_transition(); now def test_dti_tz_localize_nonexistent_shift_past_last_transition(tz). [pypi.org](https://pypi.org/project/pandas/3.1.1/)
- **Signature changed** `pandas.tests.io.test_common.TestCommonIOCapabilities.test_read_fspath_all`  

Was def test_read_fspath_all(self, reader, module, path, datapath); now def test_read_fspath_all(self, reader, module, path, path_cls, datapath). [pypi.org](https://pypi.org/project/pandas/3.1.1/)
- **Signature changed** `pandas.tests.io.test_common.TestCommonIOCapabilities.test_stringify_path_fspath`  

Was def test_stringify_path_fspath(self); now def test_stringify_path_fspath(self, path_cls). [pypi.org](https://pypi.org/project/pandas/3.1.1/)
- **Signature changed** `pandas.tests.io.test_common.TestCommonIOCapabilities.test_write_fspath_all`  

Was def test_write_fspath_all(self, writer_name, writer_kwargs, module, tmp_path); now def test_write_fspath_all(self, writer_name, writer_kwargs, module, path_cls, tmp_path). [pypi.org](https://pypi.org/project/pandas/3.1.1/)
- **Signature changed** `pandas.tests.io.test_common.TestCommonIOCapabilities.test_write_fspath_hdf5`  

Was def test_write_fspath_hdf5(self, tmp_path); now def test_write_fspath_hdf5(self, path_cls, tmp_path). [pypi.org](https://pypi.org/project/pandas/3.1.1/)

## 3.1.0

992 breaking changes, first published October 22, 2026.

- **Signature changed** `pandas.api.extensions.ExtensionArray.isna`  

Was def isna(self) -> np.ndarray | ExtensionArraySupportsAnyAll; now def isna(self) -> np.ndarray | ExtensionArrayNaResult. [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.types.union_categoricals`  

Was def union_categoricals(to_union, sort_categories: bool = False, ignore_order: bool = False) -> Categorical; now def union_categoricals(to_union: Sequence\[CategoricalIndex | Series | Categorical\], sort_categories: bool = False... [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.typing.DataFrameGroupBy.__init__`  

Was def \_\_init\_\_(self, obj: NDFrameT, keys: \_KeysArgType | None = None, level: IndexLabel | None = None, grouper: ops.BaseGrouper | None = None, exclusions: frozenset\[Hashable\] | None = None, selection: IndexLabel | None = None, as_index... [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.typing.DataFrameGroupBy.aggregate`  

Was def aggregate(self, func=None, \*args, engine=None, engine_kwargs=None, \*\*kwargs); now def aggregate(self, func=None, \*args, engine=None, engine_kwargs=None, \*\*kwargs) -> DataFrame. [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.typing.DataFrameGroupBy.cummax`  

Was def cummax(self, numeric_only: bool = False, \*\*kwargs) -> NDFrameT; now def cummax(self, numeric_only: bool = False, skipna: bool = True, \*\*kwargs) -> NDFrameT. [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.typing.DataFrameGroupBy.cummin`  

Was def cummin(self, numeric_only: bool = False, \*\*kwargs) -> NDFrameT; now def cummin(self, numeric_only: bool = False, skipna: bool = True, \*\*kwargs) -> NDFrameT. [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.typing.DataFrameGroupBy.cumprod`  

Was def cumprod(self, numeric_only: bool = False, \*args, \*\*kwargs) -> NDFrameT; now def cumprod(self, numeric_only: bool = False, skipna: bool = True, \*args, \*\*kwargs) -> NDFrameT. [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.typing.DataFrameGroupBy.cumsum`  

Was def cumsum(self, numeric_only: bool = False, \*args, \*\*kwargs) -> NDFrameT; now def cumsum(self, numeric_only: bool = False, skipna: bool = True, \*args, \*\*kwargs) -> NDFrameT. [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.typing.DataFrameGroupBy.describe`  

Was def describe(self, percentiles=None, include=None, exclude=None) -> NDFrameT; now def describe(self, percentiles=None, include=None, exclude=None) -> DataFrame. [pypi.org](https://pypi.org/project/pandas/3.1.0/)
- **Signature changed** `pandas.api.typing.DataFrameGroupBy.ewm`  

Was def ewm(self, com: float | None = None, span: float | None = None, halflife: float | str | Timedelta | None = None, alpha: float | None = None, min_periods: int | None = 0, adjust: bool = True, ignore_na: bool = False, times... [pypi.org](https://pypi.org/project/pandas/3.1.0/)

And 982 more in this version.

## 3.0.6

1 breaking change, first published September 17, 2026.

- **Signature changed** `pandas.RangeIndex.searchsorted`  

Was def searchsorted(self, value, side: Literal\['left', 'right'\] = 'left', sorter: NumpySorter | None = None) -> npt.NDArray\[np.intp\] | np.intp; now def searchsorted(self, value: NumpyValueArrayLike | ExtensionArray, side: Literal\['left'... [pypi.org](https://pypi.org/project/pandas/3.0.6/)

## 3.0.3

1 breaking change, first published May 11, 2026.

- **Signature changed** `pandas.io.common.IOArgs.__init__`  

Was def \_\_init\_\_(self, filepath_or_buffer: str | BaseBuffer, encoding: str, mode: str, compression: CompressionDict, should_close: bool = False) -> None; now def \_\_init\_\_(self, filepath_or_buffer: str | BaseBuffer, encoding: str, mode... [pypi.org](https://pypi.org/project/pandas/3.0.3/)

## 3.0.2

3 breaking changes, first published March 31, 2026.

- **Signature changed** `pandas.RangeIndex.sort_values`  

Was def sort_values(self, \*, return_indexer: bool = False, ascending: bool = True, na_position: NaPosition = 'last', key: Callable | None = None) -> Self | tuple\[Self, np.ndarray | RangeIndex\]; now def sort_values(self, \*, return_indexer... [pypi.org](https://pypi.org/project/pandas/3.0.2/)
- **Signature changed** `pandas.Timedelta.to_numpy`  

Was def to_numpy(self, dtype: npt.DTypeLike = ..., copy: bool = False) -> np.timedelta64; now def to_numpy(self, dtype: npt.DTypeLike | None = ..., copy: bool = False) -> np.timedelta64. [pypi.org](https://pypi.org/project/pandas/3.0.2/)
- **Signature changed** `pandas.Timestamp.fromisoformat`  

Was @classmethod def fromisoformat(cls, date_string: str) -> Self; now @classmethod def fromisoformat(cls, date_string: str, /) -> Self. [pypi.org](https://pypi.org/project/pandas/3.0.2/)

## 3.0.0

674 breaking changes, first published January 21, 2026.

- **Removed**  

pandas 3.0.0 removed features that were deprecated in previous releases. Upgrade to pandas 2.3 and fix warnings before moving to 3.0. [github.com](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)
- **Behavior changed**  

pandas 3.0.0 supports Python 3.11 and higher, so older Python versions can no longer install it. [github.com](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)
- **Behavior changed**  

Copy-on-Write gives consistent copy and view semantics and removes SettingWithCopyWarning, so code relying on chained assignment views may change results. [github.com](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)
- **Behavior changed**  

Strings now use a dedicated string data type by default, which can change dtypes and behavior of existing string columns. [github.com](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)
- **Default changed**  

Datetime-like data now infers a new default resolution, which can change results for existing code. [github.com](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)
- **Signature changed** `pandas.api.extensions.ExtensionArray.fillna`  

Was def fillna(self, value: object | ArrayLike | None = None, method: FillnaOptions | None = None, limit: int | None = None, copy: bool = True) -> Self; now def fillna(self, value: object | ArrayLike, limit: int | None = None, copy: bool =... [pypi.org](https://pypi.org/project/pandas/3.0.0/)
- **Signature changed** `pandas.api.extensions.ExtensionArray.map`  

Was def map(self, mapper, na_action=None); now def map(self, mapper, na_action: Literal\['ignore'\] | None = None). [pypi.org](https://pypi.org/project/pandas/3.0.0/)
- **Signature changed** `pandas.api.extensions.ExtensionArray.ravel`  

Was def ravel(self, order: Literal\['C', 'F', 'A', 'K'\] | None = 'C') -> ExtensionArray; now def ravel(self, order: Literal\['C', 'F', 'A', 'K'\] | None = 'C') -> Self. [pypi.org](https://pypi.org/project/pandas/3.0.0/)
- **Signature changed** `pandas.api.extensions.ExtensionArray.T`  

Was T: ExtensionArray; now T: Self. [pypi.org](https://pypi.org/project/pandas/3.0.0/)
- **Signature changed** `pandas.api.extensions.ExtensionArray.transpose`  

Was def transpose(self, \*axes: int) -> ExtensionArray; now def transpose(self, \*axes: int) -> Self. [pypi.org](https://pypi.org/project/pandas/3.0.0/)

And 664 more in this version.

## Check your code

These are the changes. To see which of them reach your code, [scan a public repository](https://since.dev/scan.md), or have your coding agent call `check_code` with your manifest or lockfile over [MCP](https://since.dev/docs.md#mcp). [The API](https://since.dev/docs.md#api) reads every change in every version, not only the newest. A fix pull request opens for the changes that reach a connected repository. Nothing merges or deploys.

## Put your code on continuous maintenance.

Scan a public repository now, or give your agent one line.

[Scan a repository](https://since.dev/scan.md). Any public GitHub repository. No sign-in.

### Tell your agent what changed since it was trained.

`claude mcp add --transport http since https://api.since.dev/mcp`

[Get an API key](https://app.since.dev/login?mode=signup)

Codex, Cursor and any MCP client use https://api.since.dev/mcp.

---

Every page on this site as Markdown: https://since.dev/sitemap.md. For agents: https://since.dev/llms.txt.
