Skip to content

/changelogs/pandas/pandas-2-to-3

pandas 2 to 3: Copy-on-Write, the str dtype and other breaking changes

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated 2026-10-20
tool
pandas
versions
2.x → 3.0

pandas 3.0.0 was released on 2026-01-21 (3.0.6 on 2026-09-17). Two changes affect most code: Copy-on-Write is now the only behaviour, so any subset or method result behaves as a copy, and string data gets a dedicated str dtype instead of object. The project recommends upgrading to pandas 2.3 first, which warns about most affected patterns.

Strings: object becomes str

bash
cat > dtypes.py <<'PY'
import pandas as pd
s = pd.Series(["a", "b", None])
print("pandas", pd.__version__, "-> dtype:", s.dtype, "| missing value:", repr(s[2]))
PY
uv run -q --no-project --python 3.13 --with pandas==2.2.3 python dtypes.py
python dtypes.py

Output

pandas 2.2.3 -> dtype: object | missing value: None
pandas 3.0.6 -> dtype: str | missing value: nan

The str dtype only holds strings or missing values, and its missing value is NaN. Code that checks dtype == object, or stores non-strings in a text column, needs changes.

Copy-on-Write: chained assignment stops working

bash
cat > chained.py <<'PY'
import warnings, pandas as pd
warnings.simplefilter("ignore")
df = pd.DataFrame({"a": [1, 2, 3], "b": [10, 20, 30]})
df["b"][df["a"] > 1] = 0           # chained assignment
print("pandas", pd.__version__, "-> b:", df["b"].tolist())
PY
uv run -q --no-project --python 3.13 --with pandas==2.2.3 python chained.py
python chained.py

Output

pandas 2.2.3 -> b: [10, 0, 0]
pandas 3.0.6 -> b: [10, 20, 30]

In pandas 2.2 (without Copy-on-Write enabled) the chained assignment changed df; in pandas 3 it never does. Use df.loc[df["a"] > 1, "b"] = 0.

Other changes to check

  • Python 3.11+ is required; minimum versions of NumPy and optional dependencies were raised.
  • Datetime resolution is inferred from the input instead of always nanoseconds.
  • Removed deprecations: everything deprecated during 2.x is gone; run your code on pandas 2.3 with warnings enabled to find it.
  • Fewer defensive copies: .copy() calls added to silence SettingWithCopyWarning are no longer needed.

Upgrade path

  1. Upgrade to pandas 2.3 and run tests with -W error::FutureWarning -W error::DeprecationWarning.
  2. Optionally enable the new behaviour early on 2.x: pd.options.mode.copy_on_write = True and pd.options.future.infer_string = True.
  3. Upgrade to 3.0 and fix remaining dtype == object checks.

Sources