pandas
map
applymap
apply
data manipulation

Difference between map, applymap and apply methods in Pandas

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Pandas offers three similarly named methods for applying transformations to data: map, applymap, and apply. Each operates at a different level of granularity, from individual elements to entire rows or columns. Understanding which one to reach for saves debugging time and often produces faster, more readable code.

Series.map() for Element-wise Substitution

Series.map() transforms each element in a Series using a function, a dictionary, or another Series. It is designed exclusively for Series objects, not DataFrames.

python
1import pandas as pd
2
3s = pd.Series(["cat", "dog", "bird", "cat"])
4
5# Using a dictionary for substitution
6label_map = {"cat": 0, "dog": 1, "bird": 2}
7print(s.map(label_map))
8# 0    0
9# 1    1
10# 2    2
11# 3    0

You can also pass a function to map().

python
1s = pd.Series([1, 2, 3, 4])
2print(s.map(lambda x: x ** 2))
3# 0     1
4# 1     4
5# 2     9
6# 3    16

When a dictionary is used and a value has no matching key, map() inserts NaN for that element. This makes it ideal for clean lookup-style replacements where missing mappings should be flagged.

DataFrame.applymap() for Element-wise Operations

applymap() applies a function to every single element in a DataFrame. It is the DataFrame counterpart to Series.map().

python
1import pandas as pd
2
3df = pd.DataFrame({
4    "A": [1.234, 2.567, 3.891],
5    "B": [4.123, 5.456, 6.789],
6})
7
8formatted = df.applymap(lambda x: round(x, 1))
9print(formatted)
10#      A    B
11# 0  1.2  4.1
12# 1  2.6  5.5
13# 2  3.9  6.8

Use applymap() when you need to transform every cell with the same scalar function, such as formatting numbers, converting types, or applying string operations to an entire DataFrame.

Rename in Pandas 2.1 - DataFrame.map()

Starting with pandas 2.1, applymap() was renamed to DataFrame.map(). The old name still works but raises a FutureWarning. New code should use map() on DataFrames.

python
1import pandas as pd
2
3df = pd.DataFrame({
4    "A": [1, 2, 3],
5    "B": [4, 5, 6],
6})
7
8# Pandas 2.1+ recommended syntax
9result = df.map(lambda x: x * 10)
10print(result)
11#     A   B
12# 0  10  40
13# 1  20  50
14# 2  30  60

The behavior is identical. Only the method name changed for consistency, since Series.map() already existed and having both map and applymap on different objects was confusing.

DataFrame.apply() for Row or Column Operations

apply() works along an axis of a DataFrame, passing an entire row or column as a Series to your function. This makes it suitable for aggregate or multi-column calculations.

python
1import pandas as pd
2
3df = pd.DataFrame({
4    "math": [90, 80, 70],
5    "science": [85, 95, 75],
6    "english": [88, 78, 92],
7})
8
9# Apply along axis=1 to compute row-wise mean
10df["average"] = df.apply(lambda row: row.mean(), axis=1)
11print(df)
12#    math  science  english    average
13# 0    90       85       88  87.666667
14# 1    80       95       78  84.333333
15# 2    70       75       92  79.000000

With axis=0 (the default), apply() passes each column as a Series.

python
1# Column-wise: get the range of each column
2print(df[["math", "science", "english"]].apply(lambda col: col.max() - col.min()))
3# math       20
4# science    20
5# english    14

apply() can return a scalar, a Series, or a DataFrame, giving it far more flexibility than element-wise methods.

Using apply() with Custom Multi-column Logic

A powerful pattern is using apply() with axis=1 to create new columns based on multiple existing columns.

python
1import pandas as pd
2
3df = pd.DataFrame({
4    "price": [100, 200, 50],
5    "quantity": [2, 1, 5],
6    "discount": [0.1, 0.0, 0.2],
7})
8
9def compute_total(row):
10    return row["price"] * row["quantity"] * (1 - row["discount"])
11
12df["total"] = df.apply(compute_total, axis=1)
13print(df)
14#    price  quantity  discount  total
15# 0    100         2       0.1  180.0
16# 1    200         1       0.0  200.0
17# 2     50         5       0.2  200.0

Note that for simple arithmetic like the example above, vectorized operations (df["price"] * df["quantity"] * (1 - df["discount"])) are significantly faster. Reserve apply() for logic that cannot be expressed as vectorized operations.

Comparison Table

FeatureSeries.map()DataFrame.applymap() / DataFrame.map()DataFrame.apply()
Works onSeries onlyDataFrame (every element)DataFrame (row or column)
Input to functionSingle elementSingle elementEntire row or column
Accepts dict/SeriesYesNoNo
Typical use caseValue substitutionCell-level formattingRow/column aggregation
ReturnsSeriesDataFrameSeries or DataFrame
Pandas 2.1+ nameSeries.map()DataFrame.map()DataFrame.apply()

Common Pitfalls

  • Using apply() for element-wise operations - Calling df.apply(lambda x: x * 2) works but is slower than df.applymap(lambda x: x * 2) or vectorized df * 2 because apply() passes entire columns rather than individual values.
  • Forgetting axis parameter in apply() - The default axis=0 passes columns, not rows. Omitting axis=1 when you intend to process rows produces confusing results instead of an error.
  • Using applymap() on pandas 2.1+ - While it still works, applymap() raises a deprecation warning. Migrate to DataFrame.map() to keep your code future-proof.
  • Passing a dict to map() with missing keys - Keys not present in the mapping dictionary produce NaN values. Use Series.replace() instead if you want unmatched elements to remain unchanged.
  • Choosing apply() over vectorized operations - apply() runs a Python function per row or column, which is orders of magnitude slower than NumPy-backed vectorized operations. Always check if pandas offers a built-in method before reaching for apply().

Summary

  • Series.map() transforms individual elements in a Series and accepts functions, dictionaries, or Series for substitution.
  • DataFrame.applymap() applies a scalar function to every cell in a DataFrame and was renamed to DataFrame.map() in pandas 2.1.
  • DataFrame.apply() passes entire rows or columns to a function, making it suitable for aggregations and multi-column logic.
  • Use map() for lookup-style replacements, applymap()/DataFrame.map() for uniform cell formatting, and apply() for row-level or column-level computations.
  • Prefer vectorized pandas and NumPy operations over apply() whenever possible for better performance.
  • Always specify axis=1 explicitly when using apply() on rows to avoid defaulting to column-wise behavior.

Course illustration
Course illustration

All Rights Reserved.