What’s new in 3.2.0 (Month XX, 2027)#

These are the changes in pandas 3.2.0. See Release notes for a full changelog including other versions of pandas.

Enhancements#

enhancement1#

enhancement2#

Other enhancements#

Notable bug fixes#

These are bug fixes that might have notable behavior changes.

notable_bug_fix1#

notable_bug_fix2#

Backwards incompatible API changes#

Increased minimum versions for dependencies#

Some minimum supported versions of dependencies were updated. If installed, we now require:

Package

Minimum Version

Required

Changed

X

X

For optional libraries the general recommendation is to use the latest version. The following table lists the lowest version per library that is currently being tested throughout the development of pandas. Optional libraries below the lowest tested version may still work, but are not considered supported.

Package

Minimum Version

Changed

X

See Dependencies and Optional dependencies for more.

Other API changes#

  • Styler now displays missing float values as NaN rather than nan by default, matching DataFrame (GH 12710)

  • Index now displays missing float values as NaN rather than nan in its repr, matching Series and DataFrame (GH 64733)

  • DataFrame.copy() and Series.copy() with deep=True (the default), and ArrowExtensionArray.copy(), now copy pyarrow-backed data instead of sharing its memory, so a copy no longer keeps the original’s memory alive (GH 61930)

  • DataFrame.query() now raises a ValueError when the expression does not evaluate to a boolean array, instead of silently using the result as row labels; use DataFrame.loc for label selection (GH 8560)

Deprecations#

deprecation1#

deprecation2#

Other deprecations#

Performance improvements#

Bug fixes#

Categorical#

Datetimelike#

Timedelta#

Timezones#

  • Bug in DataFrame.query() and DataFrame.eval() comparing a timezone-aware datetime column to a string without a UTC offset raising TypeError or returning incorrect results; the string is now localized to the column’s timezone, as in df["col"] < "2000-01-02" (GH 26236)

Numeric#

Conversion#

Strings#

Interval#

Indexing#

  • Bug in DataFrame.__setitem__() silently corrupting the DataFrame when the key matched several columns and value was a timezone-aware datetime64 or period scalar, or a one-dimensional Series of either dtype; it now broadcasts across the matched columns as the other dtypes already did (GH 71078)

  • Bug in DataFrame.__setitem__() silently corrupting the DataFrame, or dropping columns of value, when the key matched several columns (duplicate or MultiIndex columns) and value was a two-dimensional array without one column per matched column; it now raises ValueError (GH 68445)

  • Bug in DataFrame.isetitem() with several positions silently corrupting the DataFrame, or dropping columns of value, when an arraylike value did not have one column per position; it now raises ValueError (GH 68445)

  • Bug in DataFrame.loc() and DataFrame.at() setitem with a single row label adding a new column from a list-like value raising or setting the wrong value (GH 30649)

  • Bug in DataFrame.loc() and DataFrame.iloc() raising or flattening a 2D value (e.g. a list of lists) set into a single object cell of a mixed-dtype DataFrame (GH 69152)

  • Bug in DataFrame.loc() and DataFrame.iloc() setitem on a 1-column DataFrame with an extension dtype raising when the column key is an all-False boolean mask or an empty list-like (GH 70232)

  • Bug in DataFrame.loc() and Series.loc() raising KeyError for a True or False label present in an object-dtype Index or the first level of a MultiIndex (GH 50165)

  • Bug in DataFrame.loc() and Series.loc() setitem with an integer slice raising TypeError where the same .loc getitem succeeds, e.g. on an index of decimal.Decimal values (GH 70219)

  • Bug in DataFrame.loc() and Series.loc() slicing with an integer or float bound that is not in the index: an object-dtype index of numbers (e.g. decimal.Decimal) raised TypeError instead of slicing by sort order, and a non-monotonic index of non-string values raised TypeError instead of KeyError (GH 70295)

  • Bug in Index.difference() dropping elements that are not in other when other was a DatetimeIndex, TimedeltaIndex or PeriodIndex and the elements were strings that parse to its values, or when other was an IntervalIndex and the elements were scalars contained in its intervals (GH 58971)

Missing#

MultiIndex#

I/O#

  • read_csv() with engine="pyarrow" now raises ValueError for the unsupported encoding_errors with bytes or file input instead of silently ignoring it (GH 71298)

  • Bug in DataFrame repr and DataFrame.to_string() where numeric column labels of differing widths were misaligned with their column’s values (GH 8300)

  • Bug in read_csv() silently misparsing non-ASCII thousands and decimal markers with the C engine; these now fall back to the Python engine with a errors.ParserWarning, or raise ValueError if engine="c" is explicitly specified (GH 71158)

  • Bug in read_csv() where a dtype given for a parse_dates column undid the date parsing, returning strings, objects, integers or categories instead of datetimes (GH 57512)

  • Bug in read_csv() with engine="c" and comment not skipping a line containing only whitespace before the comment character (GH 55916)

  • Bug in read_csv() with engine="pyarrow" silently wrapping values outside the range of the requested integer dtype instead of raising (GH 38013)

  • Bug in read_csv() with engine="python" and index_col reading a date like "20180101" as nanoseconds since the epoch when dtype is a pyarrow timestamp dtype (GH 24542)

  • Bug in read_csv(), read_excel(), read_fwf() and read_html() returning wrong column labels and treating header rows as data when header was a list not in increasing order, such as header=[1, 0] (GH 47011)

  • Bug in read_csv(), DataFrame.to_csv() and other I/O functions raising URLError for sftp:// URLs instead of reading or writing them with fsspec (GH 46765)

  • Bug in read_excel() raising ValueError when header is a list and index_col consumes all columns (GH 66372)

  • Bug in read_html() raising ImportError when lxml is not installed instead of falling back to bs4 + html5lib with the default flavor=None (GH 30281)

  • Bug in read_html() with the bs4 or html5lib parser dropping tables that have identical content, so only the first was returned (GH 49934)

  • Bug in read_orc() raising whenever filesystem was passed (GH 58746)

  • Bug in read_sas() exhausting memory instead of raising ValueError on a SAS7BDAT file that claims more rows than it can hold, when read from an uncompressed file, a zip archive, or a BytesIO (GH 70721)

  • Bug in read_sas() returning rows that were deleted from an uncompressed SAS7BDAT file (GH 15963)

  • Bug in read_sas() with format="xport" reading zeros as 5.397605e-79 (GH 50670)

  • Bug in DataFrame.to_csv() with MultiIndex columns and an unnamed index or index_label=False where a first row of missing values was read back by read_csv() as the index names and dropped; an empty index-names line is now written in this case (GH 21995)

  • Bug in DataFrame.to_csv(), DataFrame.to_json(), DataFrame.to_pickle() and similar writers where writing to a file:// URL raised for a new file and silently left an existing file unchanged; writing to other URLs such as http:// now raises instead of silently discarding the data (GH 55828)

  • Bug in DataFrame.to_excel() where a NaN label in MultiIndex columns was written as the last value of that level instead of an empty cell (GH 62340)

  • Bug in DataFrame.to_json() and Series.to_json() dropping the nanoseconds of tz-aware datetime columns and Timestamp objects, and with date_format="epoch" mis-rounding pre-1970 datetime objects or raising OverflowError for ones outside the nanosecond bounds at a coarser date_unit (GH 53473)

  • Bug in DataFrame.to_parquet() with engine="pyarrow" where a misspelled keyword argument truncated an existing file at the destination or was reported as an error about the path (GH 45815)

  • Bug in DataFrame.to_sql() creating MySQL and MariaDB datetime and time columns that silently dropped fractional seconds (GH 48435)

  • Bug in DataFrame.to_sql() with if_exists="append" or if_exists="delete_rows" writing to an existing table hanging on SQL Server while another session had uncommitted changes to an unrelated table (GH 52601)

  • Bug in DataFrame.to_sql() with if_exists="delete_rows" raising InvalidRequestError for an existing temporary table (GH 52601)

  • Bug in DataFrame.to_stata() raising ValueError for an empty DataFrame with a categorical column, and read_stata() not converting the column back to a categorical (GH 71126)

  • Bug in DataFrame.to_string(), Series.to_string() and DataFrame.to_html() ignoring na_rep for None, pd.NA, and NaT values in object-dtype columns and an explicit na_rep="NaN" for any missing value, and in DataFrame.to_xml() raising for na_rep with nullable, pyarrow-backed, or categorical columns containing missing values (GH 54872)

  • Bug in DataFrame.to_string(), Series.to_string() and their repr where values or labels containing ANSI color codes were counted toward the column width, misaligning the other rows (GH 55122)

  • Bug in displaying a Series or DataFrame in IPython with display.html.table_schema enabled printing a traceback when the data cannot be converted to JSON, such as non-UTF-8 bytes (GH 16848)

  • Bug in the display of a MultiIndex (repr, DataFrame.to_string(), DataFrame.to_html(), Styler) where distinct labels that display identically (e.g. 1 and "1") were shown as a single label; DataFrame.to_excel() merged them into one cell, losing all but the first value (GH 10796)

  • Bug in the repr of a Series or DataFrame with longdouble (e.g. float128) dtype showing values outside the float64 range as 0 or inf (GH 17809)

  • Fixed bug in read_csv() where callable skiprows received incorrect row numbers on 32-bit big-endian architectures (GH 69985)

  • Bug in ExcelWriter with engine="openpyxl" ignoring date_format and datetime_format (GH 44284, GH 59882)

  • DataFrame.to_json() and Series.to_json() with orient="table", and build_table_schema(), no longer raise AttributeError for a MultiIndex with non-string level names (GH 19129)

  • Bug in read_csv() where using engine="python" with custom converters returning unhashable types (such as lists or dicts) raised TypeError (GH 56848)

  • Bug in read_json() with typ="series" returning datetime64 dtype for all-null data instead of float64, matching DataFrame columns (GH 35464)

  • Bug in read_sas() raising IndexError or reading the wrong format or label for SAS7BDAT files with columns renamed or relabeled after the file was written (GH 60809)

  • Bug in read_sql_query() and read_sql_table() with a SQLAlchemy connection returning column labels that require sqlalchemy to unpickle (GH 52816)

  • Bug in HDFStore.append() raising ValueError: Buffer dtype mismatch instead of the “different categories” error when appending a categorical whose categories have a different dtype than the existing ones (GH 71128)

  • Bug in HDFStore.remove() deleting unselected rows when passing unsorted row coordinates (GH 71276)

  • Bug in Series.to_json() with orient="table" writing a falsy Series name such as 0, False or "" as "values" (GH 19129)

  • Bug where the pickled bytes (e.g. for joblib.hash) of a Series, DataFrame or Index with datetimelike or extension-dtype data depended on which operations had previously been run on it (GH 49170)

  • Fixed a segfault in DataFrame.to_json() and Series.to_json() with date_format="iso" when datetime conversion raises an exception (GH 69461)

Period#

Plotting#

Groupby/resample/rolling#

Reshaping#

  • Bug in concat() and the DataFrame constructor losing the freq of a DatetimeIndex or TimedeltaIndex depending on the order of the inputs (GH 64253)

  • Bug in merge_asof() with right_index=True and an empty left returning the index of right instead of left (GH 41171)

  • Bug in merge() raising ValueError when merging a numeric key with an object key that is not all strings, e.g. [1.5, None], [1.5, "a"], or an empty or all-missing key (GH 70218)

  • Bug in DataFrame.pivot() and pivot() with a list of values casting the pivoted columns to a common dtype, e.g. integers to float64 or object (GH 43547)

  • Bug in DataFrame.stack() where missing labels in the result’s MultiIndex could not be found by lookups such as .loc; unstacking such a result now places the missing label first unless sort=False is passed (GH 40366)

Sparse#

ExtensionArray#

  • Bug in read_csv() and other parsing of strings into a decimal ArrowDtype raising ArrowInvalid instead of parsing the values (GH 69838)

  • Bug in ArrowExtensionArray.factorize() ignoring use_na_sentinel=True for dictionary-encoded PyArrow data that stores nulls as dictionary values, keeping the null in the returned uniques or raising ArrowInvalid for chunked data (GH 66490)

  • Bug in Series.isin(), DataFrame.isin(), and Index.isin() on PyArrow-backed dtypes raising when values held a mix of types PyArrow cannot combine (GH 70300)

  • Bug in Series.mode() and DataFrame.mode() with dropna=False raising TypeError for "boolean" dtype (GH 70487)

  • Bug in Series.replace(), Series.where(), Series.fillna(), item assignment and related methods on a PyArrow-backed integer dtype silently truncating a fractional value, including one passed in a list (replace(2, 1.5) stored 1); these now raise TypeError, while Index.where(), Index.putmask() and Index.fillna() upcast, matching the nullable integer dtypes (GH 68638, GH 71076)

  • Bug in arithmetic and logical operations on PyArrow-backed data raising pyarrow.ArrowInvalid or pyarrow.ArrowTypeError instead of TypeError when the other operand contains objects PyArrow cannot convert (GH 62682)

  • Bug in comparisons between PyArrow-backed data and objects PyArrow cannot convert raising pyarrow.ArrowInvalid or pyarrow.ArrowTypeError; ==/!= now compare elementwise, ordered comparisons raise TypeError, and a missing value on either side propagates instead of answering False (GH 62682)

Styler#

Other#

  • Bug in api.interchange.from_dataframe() with allow_copy=False always raising RuntimeError for objects supporting the Arrow PyCapsule Interface, even when a zero-copy conversion is possible (GH 71189)

  • Bug in eval() with a multi-line expression and a target raising UndefinedVariableError when a line after the first referenced a variable (GH 31952)

  • Bug in eval(), DataFrame.eval() and DataFrame.query() where not performed a bitwise inversion instead of a logical negation, e.g. pd.eval("not True") returned -2 and df.query("a > 1 and not True") could return rows (GH 11367)

  • Bug in testing.assert_series_equal() and testing.assert_frame_equal() with check_dtype=False and check_exact=True comparing missing values against an object column differently from check_exact=False; pd.NA and NaT no longer match np.nan or None (GH 61473)

  • Bug in util.hash_array() and util.hash_pandas_object() raising UnicodeDecodeError on mixed-type object values containing non-ASCII bytes; bytes in mixed-type values now hash the same as in non-mixed ones (GH 27215)

  • Bug in DataFrame.agg(), Series.agg() and the agg methods of groupby, resample and window objects silently ignoring *args and **kwargs when func is a dict, e.g. df.agg({"a": "sum"}, min_count=1); they are now passed to each function, as with a list of functions, so a function that does not accept them now raises TypeError (GH 23889)

  • Bug in DataFrame.duplicated() and DataFrame.drop_duplicates() raising ValueError when subset is an empty list; no rows are now marked as duplicates, matching a DataFrame with no columns (GH 12869)

  • Bug in DataFrame.eval() and DataFrame.query() with engine="numexpr" where a column used again in a later line of a multi-line expression, or after a subscript such as a[a > 0], was treated as a NumPy array, raising TypeError or silently giving wrong results; eval() also no longer replaces the values of a passed resolvers mapping with NumPy arrays (GH 59062)

  • Bug in DataFrame.eval(), DataFrame.query(), and eval() with the default engine="numexpr" raising RecursionError for arithmetic between object or string columns (e.g. "a + b" on two string columns) and ValueError for an expression that is a single object or string column (GH 21088, GH 27639)

  • Bug in DataFrame.from_dict() with orient="index" silently setting a row’s values to NaN when its tuple key contained None or NaN (GH 28390)

  • Bug in DataFrame.query() and DataFrame.eval() where == and != against a string gave different results than the same comparison outside of query, e.g. returning no rows for a datetime64, timedelta64, or PeriodDtype column, or raising NotImplementedError with parser="python" (GH 54199)

  • Bug in DataFrame.query() and DataFrame.eval() where a column named inf or Inf was ignored in favor of np.inf, raising KeyError or silently returning wrong results (GH 47859)

  • Bug in DataFrame.query() and DataFrame.eval() with engine="numexpr" raising AttributeError for some comparisons and in/not in checks whose operand is a math function or unary operator, e.g. abs(a) in [1, 2] (GH 31848)

  • Bug in calling a generalized ufunc on a Series raising AttributeError when it reduced object data to a single object pandas does not recognize as a scalar, e.g. shapely.geometrycollections returning a geometry (GH 71109)

  • Bug in eval(), DataFrame.eval(), and DataFrame.query() raising on some datetime64 and timedelta64 operations, e.g. df.query("time > @now - @delta"), and returning float32 for a float32 column times a np.timedelta64 (GH 30729, GH 52559)

  • Bug in DataFrame.replace() and Series.replace() with inplace=True and a list-like or dict to_replace using memory proportional to the number of values to replace times the length of the data, raising MemoryError for large mappings (GH 25816)

Contributors#

A total of 61 people contributed patches to this release. People with a “+” by their names contributed a patch for the first time.

  • ASWANTH R +

  • Aahan G +

  • Aarya +

  • Aarya Prakash +

  • Aarya2004 +

  • Abhishek Kumar +

  • Aidan Feldman

  • Ammar Hassona +

  • Aniruktha +

  • Anushka Dudhe +

  • Atik +

  • Ayush Kumar +

  • Ayush Srivastava +

  • Breno Barreto +

  • Chaimaa Abi +

  • DeviousCardi +

  • Fangchen Li

  • Furqan Khan +

  • GON +

  • Gore Williams +

  • H23 +

  • Ishaan

  • Itssubhraneelbruv +

  • Johnny Kao +

  • Johnny Wilson Dougherty +

  • Joris Van den Bossche

  • Juan Miguel Contreras +

  • Julian Harbeck

  • Leo Camus +

  • Likhitha J +

  • Maha Rana Yadavalli +

  • Maha Yadavalli +

  • Mannava Daasaradhi +

  • Manvi Soni +

  • Matthew Roeschke

  • Minh Tuan Pham +

  • Mohd Maaz Khan +

  • N3verm1nd

  • Natalia Mokeeva

  • Odysseas Yiakoumis +

  • Parman Mohammadalizadeh +

  • Richard Shadrach

  • Ryan George +

  • S.A +

  • Saihritesh

  • SamuelOndrus +

  • Sugandh Garg +

  • TensorDevLJ +

  • Tiereonna +

  • Trinh Quoc Anh

  • Trupti603 +

  • Vincent Ngo +

  • Weijian He +

  • britz +

  • furqankhan +

  • guptaishaan

  • jbrockmendel

  • maharanay22 +

  • ump45nose

  • yuchen-xu +

  • Álvaro Kothe