Sooner or later a transformation you need is not one of pandas' built-in methods, and you want to run your own logic over the data. That is what apply, map and their relatives are for. They let you push a function through a Series or DataFrame and get a transformed result back. Used well they are powerful; used carelessly they are slow, so this tutorial covers both the how and the when.
The three tools overlap, so the key is knowing which fits each job: map for substituting values in one column, apply for column-wise or row-wise logic, and element-wise map on a whole DataFrame for cell-by-cell work.
map: substitute values in a Series
Series.map transforms each value in one column. Its most useful form takes a dictionary that translates old values to new ones, perfect for recoding categories. Start with a small illustrative sample:
import pandas as pd
df = pd.DataFrame({
"name": ["Aarti", "Bhaskar", "Chitra", "Devan"],
"grade": ["A", "B", "A", "C"],
"salary": [48000, 65000, 52000, 90000],
})
grade_points = {"A": 4.0, "B": 3.0, "C": 2.0}
df["gpa"] = df["grade"].map(grade_points)
print(df)
name grade salary gpa
0 Aarti A 48000 4.0
1 Bhaskar B 65000 3.0
2 Chitra A 52000 4.0
3 Devan C 90000 2.0
The dictionary mapped each letter grade to a number in one clean line. map also accepts a function, so df["grade"].map(str.lower) would lowercase every grade. Values not present in the dictionary become NaN, which is a useful signal for unexpected categories.
apply on a Series
Series.apply runs a function on each value, much like map, but is the idiomatic choice when you pass a function rather than a lookup. It shines with a lambda for quick inline logic:
df["salary_band"] = df["salary"].apply(
lambda s: "high" if s >= 60000 else "standard"
)
print(df[["name", "salary", "salary_band"]])
name salary salary_band
0 Aarti 48000 standard
1 Bhaskar 65000 high
2 Chitra 52000 standard
3 Devan 90000 high
Each salary passed through the function and produced a label. This is how you build derived, categorical columns from numeric ones.
apply across rows
The real power of apply is axis=1, which hands your function an entire row so you can combine several columns at once:
orders = pd.DataFrame({
"price": [100, 250, 80],
"qty": [2, 1, 5],
})
orders["total"] = orders.apply(lambda row: row["price"] * row["qty"], axis=1)
print(orders)
price qty total
0 100 2 200
1 250 1 250
2 80 5 400
With axis=1 the row argument is a Series holding that row's values, so you can reference any column by name. This is invaluable when a new value depends on the interaction of multiple columns. (For this exact multiplication, note that the vectorized orders["price"] * orders["qty"] is faster, a point we return to below.)
Element-wise across a whole DataFrame
To apply a function to every individual cell of a DataFrame, use DataFrame.map (called applymap before pandas 2.1):
nums = pd.DataFrame({"a": [1, 2], "b": [3, 4]})
print(nums.map(lambda x: x ** 2))
a b
0 1 9
1 4 16
Every cell was squared. This is for uniform, cell-level transformations across the entire table.
Prefer vectorized operations when you can
Here is the most important habit to build: apply calls your Python function once per element or row, which is slower than pandas' built-in vectorized operations that run in optimized C. Whenever a native operation exists, use it. Arithmetic, comparisons and string methods are all vectorized:
# vectorized: fast, preferred
orders["total"] = orders["price"] * orders["qty"]
df["gpa_bonus"] = df["gpa"] + 0.5
Reach for apply only when the logic genuinely cannot be expressed with vectorized operations or a map dictionary. On small datasets the speed difference is irrelevant, but on millions of rows it is the difference between seconds and minutes.
Practical usage
In real work you use map to recode categories (region codes to names, status flags to labels), apply with a lambda to bucket numbers into bands, and apply(axis=1) for the occasional multi-column calculation that has no vectorized form. A frequent pattern is cleaning: apply a small parsing function to salvage a messy column, then continue with fast vectorized code once the data is tidy. Keeping the vectorized-first mindset means you use these tools deliberately, not as a default hammer.
Common mistakes
- Reaching for apply when a vectorized op exists. Multiplying two columns or comparing values does not need apply and is much slower with it. Use direct operations first.
- Calling the function instead of passing it.
df["x"].apply(str.upper())fails; pass the function without parentheses:df["x"].apply(str.upper). - Forgetting
axis=1for row logic. By defaultapplyon a DataFrame works column by column. To operate on rows, you must setaxis=1. - Unmapped values becoming NaN silently. With
map, any value missing from your dictionary turns intoNaN. Check for unexpected NaN afterwards, or supply a default.
In interviews
Interviewers use apply questions to probe whether you understand performance, not just syntax. A common prompt is "create a derived column based on a rule," where a lambda inside apply is a fine answer, but the standout candidate adds "if this were simple arithmetic I'd vectorize it instead for speed." Expect to explain the difference between map and apply, and to know that applymap became DataFrame.map. Demonstrating that you default to vectorized operations and reserve apply for genuinely custom logic signals maturity with pandas.
Where this fits in your learning path
Custom transformations are a practical middle skill in the data analytics path. apply and map pair especially well with string methods for cleaning text, and with groupby where you sometimes apply a function per group. Understanding why vectorized code is faster connects directly to the NumPy introduction, which explains the array engine underneath. Clean, efficient transformation is a daily part of the data analyst role.
Frequently Asked Questions
What is the difference between apply and map in pandas?
How do I apply a function to a pandas column?
How do I apply a function across each row of a DataFrame?
What replaced applymap in newer pandas?
Is apply slow in pandas?
Want to Build Your Career in Data Analytics with AI?
Join CodeBegun and train with working industry engineers — Explore the Data Analytics program

