# What changed in pandas

> 86 changes in pandas 2 to 3 from its official release notes, upgrade guides and advisories: 13 breaking, 35 deprecations, 9 new APIs and options. Each one cited. Sources checked 2026-10-22. HTML: https://unstale.sh/pypi/pandas/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## pandas 3

### Breaking changes

- The default for inplace changed from False to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.drop_duplicates.html)
- The inplace parameter's default changed from False to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.drop.html)
- The positional argument is now named arg. A callable or expression is treated as a boolean mask; other list-like values select labels, and a list-like of booleans warns because it may have been intended as a mask. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html)
- The default axis is now the index for boolean masks and the columns for DataFrame label selection; expressions support only the index. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html)
- Adds a length-2 suffixes parameter for overlapping column names; either value can be None to leave that side's column names unchanged, but not both. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.join.html)
- Raises ValueError when a non-unique column label in expr still evaluates to a DataFrame, because no row mask is available. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.query.html)
- The default for inplace changed from False to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rename.html)
- The default for inplace changes from False to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sort_values.html)
- Inserting a DatetimeIndex or TimedeltaIndex as a column loses its freq, and a subsequent DataFrame.set_index() does not restore it. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reset_index.html)
- Datetime-like data has a new default resolution. (3.0.0) — [release notes](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)
- The new stack implementation is the default as of pandas 3.0; dropna and sort have no impact on its result and must remain unspecified. (3.0.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html)
- Pandas 3.0.0 supports Python 3.11 and higher. (3.0.0) — [release notes](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)

### Deprecations

- Deprecated; pass dtype=False to disable type conversion, or parse date columns with to_datetime() after reading. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- The convert_boolean keyword is deprecated and will be removed in a future version. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.convert_dtypes.html)
- The convert_floating keyword is deprecated and will be removed in a future version. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.convert_dtypes.html)
- The convert_integer keyword is deprecated and will be removed in a future version. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.convert_dtypes.html)
- The convert_string keyword is deprecated and will be removed in a future version. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.convert_dtypes.html)
- The infer_objects keyword is deprecated and will be removed in a future version. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.convert_dtypes.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.drop_duplicates.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.drop.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.eval.html)
- Selecting labels with items will be deprecated; use DataFrame.select when all requested items are present in the columns, or an Index intersection otherwise. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html)
- Selecting labels with like will be deprecated; the notes recommend filtering column labels with str.contains and regex=False instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html)
- Selecting labels with regex will be deprecated; the notes recommend filtering column labels with str.contains instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html)
- Passing a dict to the data parameter is deprecated; use the DataFrame constructor or DataFrame.from_dict() instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.from_records.html)
- lsuffix is deprecated; use suffixes instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.join.html)
- rsuffix is deprecated; use suffixes instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.join.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.query.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rename_axis.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rename.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0; its default is now <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.set_index.html)
- The verify_integrity keyword is deprecated and will be removed in a future version; check result.index.is_unique directly instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.set_index.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sort_index.html)
- The inplace keyword is deprecated since pandas 3.1.0 and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sort_values.html)
- The 'fastparquet' and 'auto' engine options are deprecated; use 'pyarrow' or omit engine to use the default. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_parquet.html)
- The dropna keyword is deprecated and will be removed in a future version; use DataFrame.dropna() before writing instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_hdf.html), [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- All float precision modes now use the same converter; the float_precision argument is deprecated and will be removed in a future version. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html), [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- Passing a non-dict to from_dict is deprecated; use the DataFrame constructor instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.from_dict.html)
- The inplace keyword is deprecated and will be removed in pandas 4.0. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.dropna.html), [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reset_index.html)
- The default engine for xlsx and xlsm files will change from openpyxl to calamine in a future version; set this option to keep the current behavior. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- This option is deprecated; use DataFrame.dropna() before writing instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- Deprecated; pass dtype=False to disable type conversion, or parse date columns with to_datetime() after reading. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- The pyxlsb engine emits a deprecation warning and will be removed in a future version; use calamine instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- float_precision is deprecated because all float precision modes now use the same converter and the argument will be removed in a future version. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html)
- The xlrd engine emits a deprecation warning and will be removed in a future version; use calamine instead. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- The future_stack parameter is deprecated and will be removed in a future pandas version. (3.0.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html)
- The sort parameter is deprecated and will be removed in a future pandas version. (3.0.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html)

### New APIs and options

- The calamine engine supports Excel formats, including xls and xlsb, as an alternative to the xlrd and pyxlsb engines. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- Adds cond for boolean masks, callables, and expressions; Series masks align to the filtered axis, while other array-like masks must match its length. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html), [docs](https://pandas.pydata.org/docs/user_guide/indexing.html)
- Adds na to control missing values in boolean masks: False or True substitutes that value, while "raise" raises a ValueError. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html), [docs](https://pandas.pydata.org/docs/user_guide/indexing.html)
- Adds a method to select columns by label or expression and include computed columns; it returns a DataFrame, and later items can refer to columns computed earlier in the call. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.select.html)
- Controls the number of threads used for parallel CSV reading; set it to 1 to disable parallel reading. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- The mode.max_threads option can cap or disable parallel parsing of sufficiently large local uncompressed files read with the C engine. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html)
- Accepts a boolean mask, callable, or pandas.col() expression to filter rows; Series masks align on the index, and other array-like masks must match its length. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/indexing.html)
- Controls how missing values in the mask are handled: they are treated as False by default, can be kept with True, or can raise an error with "raise". (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/indexing.html)
- Initial support is available for the new pd.col syntax. (3.0.0) — [release notes](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)

### Performance

- Eligible reads of large local, uncompressed files with the C engine are split into chunks and parsed in multiple threads; results match serial reads. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)

### Behavior and default changes

- The default for inplace changed from False to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.eval.html)
- Passing axis=1 filters columns instead of rows. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/indexing.html)
- The documented default for inplace changes from False to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.query.html)
- The default for inplace changed from False to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rename_axis.html)
- The documented default for allow_duplicates changes from lib.no_default to False. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reset_index.html)
- The documented default for inplace changes from False to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reset_index.html)
- The sort order is deterministic for a given input; mergesort and stable preserve the relative order of equal keys. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sort_values.html)
- Appending requires an existing table-format object and exactly matching columns in the same order; creating a key with append=True defaults format to table. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_hdf.html)
- Passing complib without complevel greater than 0 emits a UserWarning and writes the data uncompressed. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_hdf.html)
- nan_rep applies only to string columns in table format; the default uses a non-colliding sentinel, while a supplied value is read back as missing and later appends reuse the stored value. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_hdf.html)
- The signature now uses <no_default> for engine instead of 'auto'; omitting engine uses the default. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_parquet.html)
- The path may be a URL using schemes including http, ftp, s3, gs, and file; some schemes require additional packages such as s3fs for S3. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_parquet.html)
- With dtype="category", numeric and boolean categories are inferred; values that do not all parse as numeric or boolean retain string categories. (3.1.0) — [docs](https://pandas.pydata.org/docs/user_guide/io.html)
- A DatetimeIndex or TimedeltaIndex created from a column has freq=None; passing the index directly as keys preserves its freq. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.set_index.html)
- Header indices count only non-blank, non-commented lines when skip_blank_lines=True; inferred duplicate and empty labels are renamed, and header labels are strings. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html)
- The displayed default for delimiter changes from None to <no_default>. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html), [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html)
- Reading certain URL schemes may require optional packages; S3 URLs require s3fs. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html)
- A dedicated string data type is the default. (3.0.0) — [release notes](https://github.com/pandas-dev/pandas/releases/tag/v3.0.0)

### Fixes and other changes

- Files written by to_hdf use a pandas-specific layout and are intended for read_hdf() or HDFStore, not as a general-purpose interchange format for arbitrary HDF5 consumers. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_hdf.html)
- Clarifies that converters receive raw text, with empty fields passed as empty strings, before missing-value settings are applied to the returned value. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html), [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html)
- Clarifies that dtype does not change missing-value parsing; values recognized as missing remain NaN or the dtype’s NA value. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html), [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html)
- Documents that pyarrow is multithreaded and the C engine reads sufficiently large files in parallel. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html), [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html)
- Clarifies accepted header values and how inferred column labels handle duplicate and empty names. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html)
- Clarifies that independent chunk inference can produce mixed int and str values, object dtype after concatenation, and a DtypeWarning. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html), [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html)
- Documents quoting values as 0, 1, 2, or 3, corresponding to the csv.QUOTE_* constants. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html)
- File-like objects must have a read() method that accepts an optional size argument. (3.1.0) — [docs](https://pandas.pydata.org/docs/reference/api/pandas.read_table.html)
- This is the first pandas release to support Python 3.15. (3.0.6) — [release notes](https://github.com/pandas-dev/pandas/releases/tag/v3.0.6)

## pandas 2

### Breaking changes

- Copy-on-Write makes behavior more predictable: one statement cannot update more than one object, and indexing operations or methods won’t have side-effects. (2.0.0) — [docs](https://pandas.pydata.org/docs/user_guide/migration.html)

### Performance

- Starting from pandas 2.0, most optimizations enabled by Copy-on-Write are implemented and supported, with delayed copies improving average performance and memory usage. (2.0.0) — [docs](https://pandas.pydata.org/docs/user_guide/migration.html)
