apply, map & applymap
Reviewed & published by Brayan K
apply, map, and applymap are pandas methods that run your own function across data: map transforms a Series element by element, apply runs a function over a Series or over the rows and columns of a DataFrame, and applymap (now DataFrame.map) touches every single cell.
Part of the free Pandas course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Learn which tool to reach for, how the axis argument changes everything, and how lambdas keep your transformations short.
What You'll Learn in This Lesson
- Transform a Series with Series.apply(func)
- Recode values with Series.map({dict})
- Run a function down columns with axis=0
- Run a function across rows with axis=1
- Touch every cell with applymap / DataFrame.map
- Write compact lambda functions
1 Series.apply() and Series.map()
On a single column, Series.apply(func) calls your function once per value and collects the results into a new Series. Series.map does the same when given a function, but it can also take a dictionary to recode values, which is perfect for relabelling categories.
import pandas as pd
prices = pd.Series([10.0, 25.5, 8.99])
# apply a function to every value
with_tax = prices.apply(lambda p: round(p * 1.2, 2))
print(with_tax)
# 12.0, 30.6, 10.79
codes = pd.Series(["S", "M", "L", "S"])
# map with a dictionary to recode each value
labels = codes.map({"S": "Small", "M": "Medium", "L": "Large"})
print(labels.tolist())
# ['Small', 'Medium', 'Large', 'Small']
# map can also take a function, just like apply
print(codes.map(lambda c: c.lower()).tolist())
# ['s', 'm', 'l', 's']
# ✅ Expected output:
# 0 12.00
# 1 30.60
# 2 10.79
# dtype: float64
# ['Small', 'Medium', 'Large', 'Small']
# ['s', 'm', 'l', 's']2 DataFrame.apply: axis=0 vs axis=1
On a DataFrame, apply hands your function a whole Series at a time. With axis=0 (the default) each column is passed in, so you get one summary per column. With axis=1 each row is passed in, which is how you combine several columns into one new value.
import pandas as pd
df = pd.DataFrame({
"math": [80, 90, 70],
"science": [60, 85, 95],
})
# axis=0: function receives each COLUMN -> one result per column
print(df.apply(lambda col: col.max() - col.min()))
# math -> 20, science -> 35
# axis=1: function receives each ROW -> one result per row
df["total"] = df.apply(lambda row: row["math"] + row["science"], axis=1)
print(df)
# total column: 140, 175, 165
# ✅ Expected output:
# math 20
# science 35
# dtype: int64
# math science total
# 0 80 60 140
# 1 90 85 175
# 2 70 95 1653 Elementwise: applymap (now DataFrame.map)
When you want to transform every individual cell of a DataFrame the same way, use applymap. In pandas 2.1 and later this method was renamed DataFrame.map; both do exactly the same elementwise work, so you may see either name.
import pandas as pd
df = pd.DataFrame({
"a": [1.5, 2.25],
"b": [3.1, 4.999],
})
# Format every cell as a 2-decimal string.
# applymap works on all pandas versions...
print(df.applymap(lambda x: f"{x:.2f}"))
# ...and DataFrame.map is the modern equivalent (pandas 2.1+)
print(df.map(lambda x: f"{x:.2f}"))
# Both print:
# a b
# 0 1.50 3.10
# 1 2.25 5.00
# ✅ Expected output:
# a b
# 0 1.50 3.10
# 1 2.25 5.00
# a b
# 0 1.50 3.10
# 1 2.25 5.00🎯 Your Turn: Pass or Fail
Replace the blank so each score becomes "Pass" when it is 50 or more and "Fail" otherwise. The expected output is a Series with values Pass, Fail, Pass.
import pandas as pd
scores = pd.Series([72, 41, 88])
# 🎯 YOUR TURN: return "Pass" if s >= 50 else "Fail"
result = scores.apply(lambda s: "Pass" if ___ else "Fail")
print(result.tolist())
# Expected output: ['Pass', 'Fail', 'Pass']Common Errors
❌ Forgetting axis=1 for row logic
Without axis=1, apply walks columns and your row lookup like row["math"] fails or gives the wrong shape.
df.apply(lambda row: row["a"] + row["b"], axis=1) # ✅ axis=1❌ Using applymap on a Series
applymap and DataFrame.map only exist on DataFrames. On a single column use Series.apply or Series.map instead.
series.apply(my_func) # ✅ for a Series
df.map(my_func) # ✅ for a whole DataFrame🎯 Mini Challenge: Order Summary
Recode a status column with map, then build a row total with a row-wise apply.
import pandas as pd
df = pd.DataFrame({
"qty": [2, 1, 3],
"price": [9.99, 19.5, 4.0],
"status": ["P", "S", "P"],
})
# 1. Recode the status codes to words with map + a dict
df["status"] = df["status"].map({"P": "Paid", "S": "Shipped"})
# 2. Row-wise apply to compute line totals (axis=1)
df["line_total"] = df.apply(lambda r: round(r["qty"] * r["price"], 2), axis=1)
print(df)
# line_total: 19.98, 19.5, 12.0
# ✅ Expected output:
# qty price status line_total
# 0 2 9.99 Paid 19.98
# 1 1 19.50 Shipped 19.50
# 2 3 4.00 Paid 12.00❓ Frequently Asked Questions
Lesson complete — you can transform data your way!
You now know when to use map for recoding, apply for flexible per-column or per-row logic, and applymap / DataFrame.map for every cell. Lambdas keep these transformations short and readable.
Practice quiz
What can Series.map accept that Series.apply cannot?
- A function
- A lambda
- A dictionary for recoding values
- A Series of numbers
Answer: A dictionary for recoding values. map accepts a dict (or Series) to substitute values, as well as a function; apply only takes a function.
If you map a Series with a dict and a value's key is missing, what happens to that value?
- It becomes NaN
- It stays unchanged
- It raises an error
- It becomes 0
Answer: It becomes NaN. Values whose key is absent from the mapping dict become NaN.
What does the default axis=0 in DataFrame.apply pass to your function?
- Each row as a Series
- A single scalar
- The whole DataFrame
- Each column as a Series
Answer: Each column as a Series. axis=0 (the default) passes each column to the function, giving one result per column.
Which axis lets you combine several columns of the same row into one value?
- axis=0
- axis=1
- axis=2
- axis=-1 only
Answer: axis=1. axis=1 passes each row as a Series, so you can read multiple columns of that row.
Which method transforms every individual cell of a DataFrame the same way?
- DataFrame.map (formerly applymap)
- Series.map
- groupby
- merge
Answer: DataFrame.map (formerly applymap). applymap, renamed DataFrame.map in pandas 2.1+, applies a function elementwise to every cell.
What replaced the deprecated DataFrame.applymap in pandas 2.1?
- DataFrame.apply
- Series.map
- DataFrame.map
- DataFrame.transform
Answer: DataFrame.map. DataFrame.map does the same elementwise operation and is the modern name.
For df.apply(lambda col: col.max() - col.min()) on columns math=[80,90,70] and science=[60,85,95], what are the results?
- math 70, science 60
- math 20, science 35
- math 10, science 10
- An error
Answer: math 20, science 35. Per column: math 90-70=20, science 95-60=35.
Which call correctly computes a per-row total across columns 'a' and 'b'?
- df.apply(lambda r: r['a'] + r['b'])
- df.map(lambda r: r['a'] + r['b'])
- df['a'].applymap(sum)
- df.apply(lambda r: r['a'] + r['b'], axis=1)
Answer: df.apply(lambda r: r['a'] + r['b'], axis=1). Row logic needs axis=1 so each row Series is passed in.
On a single column, why use apply with a function instead of map with a dict?
- apply is always faster
- apply lets you supply default logic for unknown values
- map cannot take a function
- map only works on numbers
Answer: apply lets you supply default logic for unknown values. A function in apply can handle any input, including a default for values a dict would map to NaN.
Which method does NOT exist on a Series (only on a DataFrame)?
- apply
- map
- applymap
- head
Answer: applymap. applymap and DataFrame.map are DataFrame-only; on a Series use apply or map.
Continue this course
- Previous: idxmax & idxmin: Find the Row Behind the Max
- Next: String Operations with .str — Clean and transform text columns with vectorised string methods
- Quick reference: Pandas cheat sheet › Transforming
Frequently asked questions
What is the difference between map and apply in pandas?
Series.map is used to substitute or transform values element by element, and it accepts a dictionary, a Series, or a function. Series.apply only accepts a function but is more flexible for richer logic. On a DataFrame, apply runs a function over whole columns or rows, which map cannot do.
What does the axis argument do in DataFrame.apply?
axis=0 (the default) passes each column to your function as a Series, so you typically get one result per column. axis=1 passes each row as a Series, so you get one result per row. Use axis=1 when a new value depends on several columns of the same row.
Is applymap removed in newer pandas versions?
DataFrame.applymap was deprecated in pandas 2.1 in favour of DataFrame.map, which does the same elementwise operation. applymap still works for now but emits a warning, so prefer DataFrame.map in new code while knowing both names refer to the same idea.