# Pandas map vs applymap vs apply: Key Differences and When to Use Each

> Understand the distinct pandas map and apply methods. Learn when to use each for efficient data manipulation in pandas, avoiding the deprecated applymap.

- Repository: [pandas/pandas](https://github.com/pandas-dev/pandas)
- Tags: tutorial
- Published: 2026-02-16

---

**pandas `map` operates element-wise on individual scalar values, while `apply` operates axis-wise on entire rows or columns; `applymap` is deprecated since pandas 2.1.0 and replaced by `DataFrame.map`.**

Understanding the difference between pandas map applymap and apply methods is essential for writing efficient data transformation code. These three methods in the pandas-dev/pandas repository provide distinct approaches to applying functions to your data, ranging from element-wise scalar operations to complex axis-wise aggregations. While they may appear interchangeable at first glance, each method follows a specific internal implementation path optimized for different use cases.

## Element-Wise vs. Axis-Wise: The Core Distinction

The primary architectural difference between these methods lies in how they traverse your data structure.

**Element-wise operations** iterate over individual scalar values. Both `Series.map` and `DataFrame.map` (formerly `applymap`) fall into this category. They accept a function that takes a single value and returns a single value, applying it to every element independently. Internally, pandas uses the `map_array` routine in [`pandas/core/algorithms.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/algorithms.py) to handle these iterations efficiently.

**Axis-wise operations** traverse data along a specific dimension. `DataFrame.apply` operates on entire rows (`axis=1`) or columns (`axis=0`), passing each as a Series to your function. This allows operations that depend on multiple values within the same row or column. The implementation uses the `frame_apply` engine defined in [`pandas/core/apply.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/apply.py).

## Series.map: Element-Wise Transformations on One-Dimensional Data

`Series.map` is the go-to method for transforming individual values in a Series. According to the pandas source code in [`pandas/core/series.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/series.py) (around line 4660), this method delegates to the low-level `map_array` routine defined in [`pandas/core/algorithms.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/algorithms.py) (line 1630).

The method accepts:
- A callable (function)
- A dictionary or Series for value mapping
- An optional `engine` parameter for JIT compilation

```python
import pandas as pd

s = pd.Series([1, 2, 3, None])

# Using a callable for element-wise transformation

result = s.map(lambda x: x * 10 if pd.notna(x) else 0)
print(result)

# Output:

# 0    10.0

# 1    20.0

# 2    30.0

# 3     0.0

# dtype: float64

# Using dictionary mapping

s.map({1: 'one', 2: 'two'})

# Output:

# 0    one

# 1    two

# 2    NaN

# 3    NaN

# dtype: object

```

## DataFrame.map: Element-Wise Operations on Two-Dimensional Data

`DataFrame.map` performs element-wise transformations across an entire DataFrame. As implemented in [`pandas/core/frame.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/frame.py) (around line 1434), this method iterates over each column and delegates to `Series.map` for the actual computation.

**Important deprecation note:** `DataFrame.applymap` was deprecated in pandas 2.1.0 and renamed to `DataFrame.map`. The old name remains functional but raises a `FutureWarning` (see docstring lines 14240-14244 in [`frame.py`](https://github.com/pandas-dev/pandas/blob/main/frame.py)). New code should use `DataFrame.map`.

```python
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})

# Element-wise squaring

df_mapped = df.map(lambda x: x ** 2)
print(df_mapped)

#    A   B

# 0  1   9

# 1  4  16

# Using numpy functions element-wise

import numpy as np
df.map(np.sqrt)

```

## DataFrame.apply: Flexible Axis-Wise Function Application

`DataFrame.apply` differs fundamentally from `map` methods by operating on entire axes rather than individual elements. According to the source in [`pandas/core/frame.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/frame.py) (line 13940) and the underlying `frame_apply` engine in [`pandas/core/apply.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/apply.py), this method builds a `DataFrameApply` object that handles complex broadcasting and result-type logic.

Key characteristics:
- **Axis parameter**: `axis=0` applies function to each column; `axis=1` applies to each row
- **Return flexibility**: Can return scalars, Series, or expand list-like results into columns
- **Result types**: Control output shape with `result_type='expand'`, `'broadcast'`, or `'reduce'`

```python
df = pd.DataFrame({'A': [1, 2], 'B': [10, 20]})

# Column-wise aggregation (axis=0)

col_sum = df.apply(pd.Series.sum)
print(col_sum)

# A     3

# B    30

# dtype: int64

# Row-wise custom function (axis=1)

row_diff = df.apply(lambda row: row['B'] - row['A'], axis=1)
print(row_diff)

# 0     9

# 1    18

# dtype: int64

# Expanding list results into columns

df.apply(lambda row: [row['A'] * 2, row['B'] * 2], axis=1, result_type='expand')

#    0   1

# 0  2  20

# 1  4  40

```

## Performance Considerations and Engine Options

All three methods accept an optional `engine` parameter for performance optimization. As implemented in the underlying `map_array` routine ([`pandas/core/algorithms.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/algorithms.py)) for `map` methods and the `frame_apply` engine ([`pandas/core/apply.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/apply.py)) for `apply`, you can specify `'numba'` or other JIT compilers to accelerate computations.

**Element-wise methods** (`map`) generally offer better performance for simple scalar transformations because they avoid the overhead of constructing intermediate Series objects for each row or column. The `map_array` routine iterates directly over the underlying NumPy arrays.

**Axis-wise method** (`apply`) incurs higher overhead due to Python function calls for each row or column, but provides necessary flexibility for complex operations requiring access to multiple values simultaneously. When using `apply` with `axis=1`, consider vectorized alternatives using `df['col'].operation()` syntax for better performance.

## Summary

- **`Series.map`** performs element-wise transformations on one-dimensional data using the `map_array` routine in [`pandas/core/algorithms.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/algorithms.py), accepting callables, dictionaries, or Series mappings.
- **`DataFrame.map`** (replacing the deprecated `applymap`) applies functions element-wise across two-dimensional data by delegating to `Series.map` for each column, as implemented in [`pandas/core/frame.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/frame.py).
- **`DataFrame.apply`** operates axis-wise using the `frame_apply` engine in [`pandas/core/apply.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/apply.py), processing entire rows or columns as Series objects with flexible return type handling via `result_type` parameters.
- **`DataFrame.applymap`** is deprecated since pandas 2.1.0; migrate to `DataFrame.map` to avoid `FutureWarning` errors.
- All three methods support optional JIT compilation via the `engine` parameter (`'numba'`, etc.) for performance-critical workloads.

## Frequently Asked Questions

### What is the difference between pandas map and apply?

**`map`** operates element-wise on individual scalar values within a Series or DataFrame, while **`apply`** operates axis-wise on entire rows or columns (as Series objects). Use `map` when transforming individual values (e.g., squaring each number or mapping values to labels), and use `apply` when your calculation requires access to multiple values in the same row or column (e.g., calculating row-wise averages or custom aggregations across columns).

### Why was DataFrame.applymap deprecated in pandas?

**`DataFrame.applymap`** was deprecated in pandas 2.1.0 and renamed to **`DataFrame.map`** to align naming conventions with `Series.map` and clarify that the method performs element-wise operations. According to the source code in [`pandas/core/frame.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/frame.py) (lines 14240-14244), `applymap` now functions as an alias that raises a `FutureWarning` and forwards to `DataFrame.map`. New code should use `DataFrame.map` to avoid deprecation warnings.

### Can I use numba with pandas map and apply methods?

Yes, all three methods—**`Series.map`**, **`DataFrame.map`**, and **`DataFrame.apply`**—accept an `engine` parameter that supports JIT compilation. As implemented in [`pandas/core/algorithms.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/algorithms.py) for `map` and [`pandas/core/apply.py`](https://github.com/pandas-dev/pandas/blob/main/pandas/core/apply.py) for `apply`, you can pass `engine='numba'` to accelerate compatible functions. Note that the numba engine requires functions to use numpy-compatible operations rather than arbitrary Python objects, and the function signature must match the expected input types for the JIT compiler to generate efficient machine code.

### When should I use DataFrame.apply instead of DataFrame.map?

Use **`DataFrame.apply`** when your operation requires access to **multiple values** within the same row or column (axis-wise logic), or when you need to return complex shapes like expanding lists into columns. Use **`DataFrame.map`** (or the deprecated `applymap`) for **element-wise** scalar transformations where the function only needs to see one value at a time and returns a single scalar. For example, use `apply` to calculate row-wise averages or custom aggregations across multiple columns, and use `map` to format strings, apply mathematical functions to individual cells, or perform value lookups.