Python · medium

Explain the difference between .apply(), .map(), and vectorized ops in pandas.

Asked in Data Scientist interviews, in the Python round.

Short answer

Vectorized ops are fastest, map is element-wise on a Series, and apply is flexible but slower (row or column).

.map().apply()Vectorized
Works onA SeriesA Series or DataFrameWhole arrays
Loops in PythonYesYesNo, runs in C
Relative speedSlowSlow10 to 100 times faster
Typical useValue lookup or dict swapRow-wise logic you cannot vectorizeArithmetic, comparisons, str and dt methods
Reach for it whenMapping a small set of valuesNothing else expresses itAlways, first
All three transform a column. Only one of them is fast.

How to answer it

Definition

All three transform a column. The difference is where the loop runs, and therefore how fast it is. The table above compares them directly.

Example

# vectorized: the whole array at once, in C
df["total"] = df["price"] * df["qty"]
df["is_big"] = df["total"] > 100
df["domain"] = df["email"].str.split("@").str[1]

# map: element-wise on a Series, good for a lookup
df["region"] = df["country"].map({"GB": "EMEA", "US": "AMER"})

# apply: a Python function per row, the slow last resort
df["score"] = df.apply(lambda r: custom(r["a"], r["b"]), axis=1)

Output

%timeit df["price"] * df["qty"]                             #   1.2 ms
%timeit df.apply(lambda r: r["price"] * r["qty"], axis=1)   # 890.0 ms

Roughly 700 times slower on a million rows, for identical output. That gap is the entire reason the question is asked.

Why vectorized is faster

A vectorized operation hands the whole array to compiled code and loops there. .apply(axis=1) builds a Python Series for every row, calls a Python function, and collects the results. The work is the same; the per-row Python overhead is not.

Key points

FAQ

The 30-second answer

They all transform a column, and the difference is where the loop runs. Vectorized operations push the whole array into compiled code, so arithmetic, comparisons and the string and datetime accessors are fastest by a wide margin. map is element-wise on a Series and is what I use for a dictionary lookup. apply with axis one is the flexible one and the slowest, because it builds a Python object per row.
In practice I try to express it vectorized first, use np.where or np.select for conditional logic, and only fall back to apply when the logic genuinely cannot be written over arrays. On a million rows the difference is a couple of milliseconds against most of a second.

In the interview

Practice this for real