Ten pandas answers that changed in pandas 3, and what 3.0.5 actually prints
I write practice questions for pandas, and every snippet has to run before its answer is kept. When I moved the whole bank to pandas 3.0.5, a surprising number of answers I had written from memory stopped being true. Some changes are loud and raise an error. The worse ones just give you a different result.
Here are ten, each run in a fresh interpreter on pandas 3.0.5. This story was written with the assistance of an AI writing program, and every output in it comes from actually running the snippet.
1. Text columns are no longer object
s = pd.Series(['a', 'b', None])
print(s.dtype)
print(s.tolist())
str
['a', 'b', nan]
The dtype is str, and the missing value comes back as nan, not None. Code that checks s.dtype == object to find text columns now finds nothing. Use pd.api.types.is_string_dtype(s).
2. Chained assignment does nothing
df = pd.DataFrame({'a': [1, 2, 3]})
df['a'][0] = 100
print(df['a'].tolist())
[1, 2, 3]
Copy-on-Write is the default, so df['a'] hands you something that behaves like a copy and the write never reaches df. pandas does emit a ChainedAssignmentError warning, but it is easy to miss in a notebook. Write df.loc[0, 'a'] = 100.
3. inplace=True does not always return None
df = pd.DataFrame({'a': [3.0, None, 1.0]})
print(type(df.fillna(0, inplace=True)).__name__)
print(df.sort_values('a', inplace=True))
DataFrame
None
fillna with inplace=True now returns the frame, sort_values still returns None. The old habit of df = df.something(inplace=True) works for one and wipes out your frame with the other. Drop inplace and assign the result.
4. Dates parse to microseconds
print(pd.to_datetime(pd.Series(['2024-01-01', '2024-02-01'])).dtype)
datetime64[us]
Not datetime64[ns] any more. It matters when you compare dtypes in a test, or write to parquet and read the file back with another tool.
5. stack keeps missing values
df = pd.DataFrame({'x': [1.0, np.nan]})
print(len(df.stack()))
2
Older versions dropped the NaN and returned 1 entry. If a count downstream depends on stack(), it just went up.
6. freq='M' is gone
pd.date_range('2024-01-31', periods=2, freq='M') # ValueError
pd.date_range('2024-01-31', periods=2, freq='ME') # 2024-01-31, 2024-02-29
Month end is 'ME' now, and 'M' raises a ValueError whose message ends with 'M' is no longer supported for offsets. Please use 'ME' instead. Same story for quarter and year end, 'Q' and 'Y' raise, 'QE' and 'YE' work.
7. freq='H' is gone too
pd.date_range('2024-01-01', periods=2, freq='H') # ValueError
pd.date_range('2024-01-01', periods=2, freq='h') # 00:00, 01:00
Hours and seconds went lowercase, 'h' and 's', and minutes are 'min'. The old 'H', 'T' and 'S' all raise, and for 'H' the message ends with Did you mean h?
8. groupby().apply() no longer sees the grouping column
df = pd.DataFrame({'k': ['a', 'a', 'b'], 'v': [1, 2, 3]})
print(df.groupby('k').apply(lambda g: list(g.columns)).tolist())
[['v'], ['v']]
Inside the function each group now holds only v. A lambda that reads g['k'] raises a KeyError. If you need the key, it is in g.name.
9. fillna(method=...) raises
s = pd.Series([1.0, None, 3.0])
s.fillna(method='ffill') # TypeError
print(s.ffill().tolist())
[1.0, 1.0, 3.0]
The method argument was removed, and the error reads NDFrame.fillna() got an unexpected keyword argument 'method'. ffill() and bfill() are the only way now.
10. Adding a number to a text column raises
s = pd.Series(['id'])
s + 1 # TypeError
print((s + '1').tolist())
['id1']
The str dtype refuses to mix text and numbers, with operation 'add' not supported for dtype 'str' with object of type <class 'int'>. Convert explicitly, s + str(1), or s + other.astype(str) for a whole column.
Where this came from
These are from a bank of 255 pandas questions that I rebuilt on 3.0.5, where every option comes with the reason it is right or wrong. Twenty of them are free to play in the browser at thibaudlepan77-svg.github.io/interview-questions-verified, no account. The full set is a PDF on Ko-fi, and there is a data bundle with SQL, Python and NumPy alongside. The NumPy side got the same treatment in ten NumPy answers that changed in NumPy 2.
If one of these prints something different on your machine, tell me your version and the output. I would rather fix the question than defend it.
Did this save you a lookup? Buy me a coffee on Ko-fi.