pandas apply KeyError (missing axis=1)
df.apply(lambda row: row['price']) raising KeyError: 'price' for a column that exists means you forgot axis=1: by default apply passes each column, indexed by row labels, not each row. Add axis=1, or replace the apply with a vectorised column expression. Tested on pandas 2.3.3 and 3.1.0.
1. The cause: apply passes columns unless you say axis=1
import pandas as pd
df = pd.DataFrame({"price": [2.0, 3.0], "qty": [5, 4]})
try:
df.apply(lambda row: row["price"] * row["qty"])
except KeyError as e:
print("KeyError:", e)
df.apply(lambda col: print(type(col).__name__, col.name, col.index.tolist()))
print(df.apply(lambda row: row["price"] * row["qty"], axis=1).tolist())
Output, identical on pandas 2.3.3 and 3.1.0:
KeyError: 'price'
Series price [0, 1]
Series qty [0, 1]
[10.0, 12.0]
DataFrame.apply defaults to axis=0: your function receives each column as a Series whose index is the row labels [0, 1]. So row["price"] looks for a row labelled price and raises KeyError: 'price', naming a column that plainly exists. Adding axis=1 passes one row at a time, indexed by column names.
2. Better: skip apply, or use .get for optional columns
import pandas as pd
df = pd.DataFrame({"price": [2.0, 3.0], "qty": [5, 4]})
df["total"] = df["price"] * df["qty"]
print(df["total"].tolist())
rows = pd.DataFrame({"price": [2.0, None]})
print(rows.apply(lambda r: r.get("qty", 1) * r["price"], axis=1).tolist())
Output, identical on pandas 2.3.3 and 3.1.0:
[10.0, 12.0]
[2.0, nan]
For arithmetic between columns, a vectorised expression gives the same result as the axis=1 apply without a Python call per row. If the KeyError is real, because some frames lack the column, a row is a Series, so r.get("qty", 1) returns a default instead of raising. Missing values propagate as nan rather than raising. If the function itself fails on some values, see pandas apply errors='coerce'.
Related: KeyError on a column that exists · KeyError: not in index · pivot_table KeyError.
Frequently asked questions
Why does pandas apply give KeyError for an existing column?
DataFrame.apply defaults to axis=0, so the function gets columns indexed by row labels; row['col'] then looks up a row label. Pass axis=1 to get rows.
How do I avoid KeyError in apply when a column might be missing?
Each row is a Series, so use row.get('col', default) instead of row['col'].
Is apply with axis=1 slow?
It calls your Python function once per row. For arithmetic between columns, df['a'] * df['b'] gives the same result without the per-row call.
Written with AI assistance. Measured on 2026-10-23 in the python:3-alpine Docker image (Python 3.14.7) with pandas 2.3.3 and pandas 3.1.0. Outputs pasted unedited. PlainTables is our extension; Python and pandas are free.