Skip to main content
v2026.11,986 entries · CC-BY 4.0

pandas map: Series.map and DataFrame.map Syntax, Examples and Pitfalls

How pandas map works: recode values with a dict or function, handle NaN with na_action, and avoid silent missing values.

Written and maintained by CASRAI Editorial Board

Published

On this page

pandas map usually means Series.map(), the pandas method that replaces each value in a column using a dictionary, a function or another Series. Since pandas 2.1.0 the same idea exists for a whole table as DataFrame.map(). This guide is for researchers and analysts recoding survey, lab or registry data in Python, and it ends with the failure modes that silently produce missing values.

What pandas map is used for in research

Series.map() is an element-wise lookup: every value in a column goes in, one value per input comes out, and the result is a new Series with the same index as the original. In research data work the typical jobs are recoding numeric survey codes into labels, translating site or instrument identifiers into names, and applying a small cleaning function to one text column. Whole-table, element-wise work uses DataFrame.map().

pandas map versus apply, replace and applymap

Method Operates on Use it when
Series.map(func, na_action=None) One column, value by value You have a dict, Series or one-value-in, one-value-out function
DataFrame.map(func, na_action=None) Every cell of a DataFrame The same single-value function applies to the whole table (added in pandas 2.1.0)
DataFrame.applymap Every cell Older name for DataFrame.map; migrate df.applymap(f) to df.map(f)
DataFrame.apply Whole rows or columns The function needs a full row or column; see pandas apply
DataFrame.replace Matching values Only some values change and the rest should stay as they are

The pandas documentation lists DataFrame.apply, DataFrame.replace and Series.map as the related methods for DataFrame.map.

Install or access

pandas is installed from the official project: see the installation page at pandas.pydata.org. Both methods are part of the core library, so no extra package is needed. Check your version with import pandas as pd; pd.__version__, because DataFrame.map needs pandas 2.1.0 or later, and the engine argument and **kwargs on Series.map were added in 3.0.0.

Step-by-step: recode survey codes with Series.map

Signature in the pandas 3.0 documentation: Series.map(func=None, na_action=None, engine=None, **kwargs). The first parameter is func in current docs (older documentation calls it arg), and it accepts a function, a dict or a Series.

  1. Import pandas and load the column. A small illustrative example: import numpy as np; import pandas as pd; s = pd.Series([1, 2, 3, 9, np.nan]), where 1 to 3 are valid Likert codes, 9 is an invalid code and the last value is missing.
  2. Define the lookup: labels = {1: 'Strongly disagree', 2: 'Disagree', 3: 'Neutral'}.
  3. Apply it: s.map(labels).
  4. Assign the result to a new column so the raw codes stay available for audit: df['q1_label'] = df['q1'].map(labels).
  5. Count the unmapped values before moving on: compare df['q1_label'].isna().sum() with df['q1'].isna().sum(). Any difference is a code missing from your dictionary.

Map with a function

Pass any callable that takes one value and returns one value, for example s.map('I am a {}'.format). DataFrame.map works the same way across all cells: df.map(lambda x: len(str(x))). Extra keyword arguments can be passed through, as in df.map(round, ndigits=1) from the pandas documentation example.

Output and how to read it

Run in pandas 3.0.5, the Likert example returns ['Strongly disagree', 'Disagree', 'Neutral', nan, nan]. The code 9 and the original missing value both become NaN, which is the documented behaviour: with a dict, values that are not found as keys become NaN. Because the two cases look identical in the output, compare the result against the source column rather than trusting the label column alone.

If the dictionary is a subclass that defines __missing__, such as collections.defaultdict, the default is used instead. With defaultdict(lambda: 'Other', labels) the same input returns ['Strongly disagree', 'Disagree', 'Neutral', 'Other', 'Other'], which also labels the missing value ‘Other’. Decide whether that is what the analysis plan intends.

The na_action argument

na_action accepts None (default) or 'ignore'. With 'ignore', NaN is propagated without being passed to the mapping. This matters for functions: pd.Series(['cat', np.nan]).map('I am a {}'.format) returns 'I am a nan' for the missing value, a string that no longer counts as missing. Adding na_action='ignore' keeps it as NaN.

Troubleshooting

Unexpected NaN after mapping

Some value was not a key in the dictionary. Check for type mismatches (the string '1' does not match the integer 1), stray whitespace in text codes, and codes you did not anticipate. List them with df.loc[df['q1_label'].isna() & df['q1'].notna(), 'q1'].unique().

Missing values turned into the text ‘nan’

A function mapped without na_action='ignore' received NaN. Add the argument or handle missing values inside the function.

Categorical columns

For a categorical Series, the pandas documentation states that the function is applied only to the categories, so it is called once per unique category rather than once per row.

Engine error

The engine argument (new in pandas 3.0.0) is only for functions decorated with a supported JIT such as numba.jit; passing it with a dict or Series raises an error.

Slow code on large tables

The pandas documentation advises that calling a Python function on each element is slow and that vectorised operations are preferable, for example squaring a frame with df ** 2 instead of mapping a lambda. Use map for lookups and genuinely element-wise logic, and vectorised operators for arithmetic. To keep only rows matching a set of values, see pandas isin; to drop rows with missing values after mapping, see pandas dropna.

Free alternatives

Task Alternative in pandas
Change only some values, leave the rest Series.replace or DataFrame.replace
Operate on whole rows or columns DataFrame.apply (guide)
Element-wise arithmetic Vectorised operators such as df ** 2
Older code using applymap DataFrame.map

If you are building the table first, see how to create a DataFrame in Python.

FAQ

What does pandas map do?

It substitutes each value of a Series using a dict, a Series or a function and returns a Series with the same index.

Is it pandas.map or Series.map?

There is no top-level pd.map. Call Series.map on a column or DataFrame.map on a table.

What replaced applymap?

DataFrame.map, added in pandas 2.1.0. Replace df.applymap(f) with df.map(f).

What happens to values missing from my dictionary?

They become NaN, unless the dict is a subclass with __missing__ such as defaultdict.

Sources

  • pandas documentation: pandas.Series.map (pandas 3.0 docs, read 2026-11-08).
  • pandas documentation: pandas.DataFrame.map (read 2026-11-08).
  • Example outputs above were run in pandas 3.0.5.

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about pandas map: Series.map and DataFrame.map Syntax, Examples and Pitfalls

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →