What's New in pandas 3
The pandas 3 changes you will notice when reading older tutorials: the str dtype, Copy-on-Write, applymap → map, inplace guidance and new frequency aliases.
This course runs pandas 3 (the playground uses pandas 3.0.2). Most YouTube videos, blogs and Stack Overflow answers were written for pandas 1.x or 2.x, so sometimes the output on your screen will look slightly different from the tutorial. This topic lists the changes you will actually meet, so they never confuse you.
Definition
pandas 3.0 is a major release of pandas (2026) that makes a few long-planned breaking changes: text gets a dedicated
strdtype, Copy-on-Write becomes the only behaviour, and several deprecated functions and aliases (such asDataFrame.applymap) are removed.
- Major release — the first number changed (2 → 3). By convention, major versions are allowed to change behaviour that old code relied on.
- Breaking change — code that worked before may now print something different, raise an error, or silently do nothing.
- Deprecated — marked "will be removed later" (pandas 2 showed a
FutureWarning). In pandas 3 many of those are now gone.
Summary table
| Area | pandas 2 (old tutorials) | pandas 3 (this course) |
|---|---|---|
| Text column dtype | object | str |
| Missing text value | None / NaN in an object column | NaN in a str column |
df["a"][0] = 5 | sometimes modified df + SettingWithCopyWarning | never modifies df (Copy-on-Write) |
SettingWithCopyWarning | very common | removed — no longer exists |
| Elementwise on a DataFrame | df.applymap(func) | df.map(func) (applymap removed) |
| Month-end frequency | "M" | "ME" |
| Hour / minute frequency | "H", "T" | "h", "min" |
| Parsed datetimes | datetime64[ns] | resolution inferred, e.g. datetime64[us] |
inplace=True | common in tutorials | discouraged — reassign instead |
fillna(method="ffill") | deprecated | removed → use .ffill() / .bfill() |
1. Text columns get the str dtype
python
import pandas as pd
teams = pd.Series(["MI", "CSK", None, "RCB"])
print(teams)
print(teams.dtype)
print(teams.str.lower())text
0 MI
1 CSK
2 NaN
3 RCB
dtype: str
str
0 mi
1 csk
2 NaN
3 rcb
dtype: strHow it works: in pandas 2 this Series would print dtype: object — a generic "any Python object" type. pandas 3 recognises that every value is text (or missing) and gives it the dedicated str dtype. The missing value shows as NaN, and .str string methods work as before. You will see str in df.dtypes and df.info().
Note (pandas 3): A column that mixes text with other types (e.g.
["MI", 7, "RCB"]) is stillobject. Old code that checksdtype == objectto find text columns should usepd.api.types.is_string_dtype(col)instead.
2. Copy-on-Write (CoW) is always on
Copy-on-Write means that any DataFrame or Series you derive from another one (by selecting columns, filtering rows, slicing…) behaves as an independent copy. Changing the derived object never changes the original, and vice versa. Internally pandas avoids actually copying data until one of them is modified — hence "copy on write".
The most visible effect is on chained assignment — two indexing steps in a row:
python
df = pd.DataFrame({"player": ["Kohli", "Rohit", "Dhoni"], "runs": [50, 30, 12]})
df["runs"][0] = 999 # chained: df["runs"] first, then [0] = ...
print(df)text
player runs
0 Kohli 50
1 Rohit 30
2 Dhoni 12pandas also prints a ChainedAssignmentError warning: "A value is being set on a copy of a DataFrame or Series through chained assignment. Such chained assignment never works…". df is unchanged because df["runs"] behaves as a copy. The fix is one indexing step with .loc:
python
df.loc[0, "runs"] = 999
print(df)text
player runs
0 Kohli 999
1 Rohit 30
2 Dhoni 12Filtering also gives you a safe, independent object — no more SettingWithCopyWarning:
python
df = pd.DataFrame({"player": ["Kohli", "Rohit", "Dhoni"], "runs": [50, 30, 12]})
top = df[df["runs"] > 20]
top["runs"] = top["runs"] + 100
print(df)
print(top)text
player runs
0 Kohli 50
1 Rohit 30
2 Dhoni 12
player runs
0 Kohli 150
1 Rohit 1303. applymap → map
DataFrame.applymap (apply a function to every cell) was renamed to DataFrame.map in pandas 2.1 and removed in pandas 3:
python
nums = pd.DataFrame({"strike_rate": [138.456, 129.13], "average": [37.268, 29.581]})
print(nums.map(lambda x: round(x, 1)))text
strike_rate average
0 138.5 37.3
1 129.1 29.6Calling nums.applymap(...) now raises AttributeError: 'DataFrame' object has no attribute 'applymap'.
4. inplace=True — prefer reassignment
Many methods (sort_values, rename, drop, fillna, reset_index…) accept inplace=True, which changes the object and returns None:
python
df = pd.DataFrame({"player": ["Kohli", "Rohit", "Dhoni"], "runs": [50, 30, 12]})
result = df.sort_values("runs", inplace=True)
print(result)
df = df.sort_values("runs") # recommended style
print(df)text
None
player runs
2 Dhoni 12
1 Rohit 30
0 Kohli 50It still works in pandas 3, but the pandas team recommends reassignment (df = df.method(...)): it is not faster (with CoW there is no saved copy), it cannot be chained, and the None return value causes bugs like df = df.dropna(inplace=True) (which sets df to None!).
5. Frequency aliases and datetimes
Upper-case aliases were replaced: use "ME" (month end), "YE" (year end), "QE" (quarter end), "h" (hour), "min" (minute), "s" (second). Also, pd.to_datetime now infers the time resolution, so you will often see datetime64[us] (microseconds) where old tutorials show datetime64[ns]. The dates themselves are identical.
Common mistakes
- ❌
df["col"][row] = value(chained assignment). ✅df.loc[row, "col"] = value. - ❌
df = df.dropna(inplace=True)→dfbecomesNone. ✅df = df.dropna(). - ❌
df.applymap(func). ✅df.map(func). - ❌
freq="M"orfreq="H". ✅freq="ME",freq="h". - ❌ Panicking when you see
strinstead ofobjectfor text. ✅ It is the new, better text dtype — all.strmethods work.
Interview tip
Q: What is Copy-on-Write in pandas, and what problem does it solve?
A: With CoW, every derived DataFrame/Series behaves like a copy, but data is only physically copied when one of them is modified. It removes the old, confusing "is this a view or a copy?" question (and SettingWithCopyWarning): modifying a subset never changes the parent, and the only way to change an object is to modify it directly, e.g. with df.loc[...] = ....
Key points to remember
- pandas 3 gives text columns the dedicated `str` dtype instead of `object`.
- Copy-on-Write is always on: derived objects behave as independent copies.
- Chained assignment like df['a'][0] = 5 never modifies df — use df.loc[0, 'a'] = 5.
- SettingWithCopyWarning no longer exists in pandas 3.
- DataFrame.applymap was removed — use DataFrame.map for element-wise functions.
- Prefer df = df.method(...) over inplace=True; inplace returns None and is not faster.
- Use frequency aliases 'ME', 'YE', 'h', 'min'; parsed dates often show datetime64[us].
Try it yourself
The new str dtype
Copy-on-Write: chained assignment vs .loc
map instead of applymap, reassignment instead of inplace
Practice: fix the old-style code
Revision Flashcards
Tap a card to flip it and see the answer.
