Pandas: Cannot setitem on a Categorical with a new category

avatar
Borislav Hadzhiev

Last updated: Apr 12, 2024
3 min

banner

# Pandas: Cannot setitem on a Categorical with a new category

The Pandas "TypeError: Cannot setitem on a Categorical with a new category (X), set the categories first" occurs when you try to assign values outside the categories of a Categorical column.

Use the Series.map() method to solve the error.

Here is an example of how the error occurs.

main.py
import pandas as pd df = pd.DataFrame({ 'A': [100, 0] }) print(df) df['A'] = pd.Categorical(df['A']) # ⛔️ TypeError: Cannot setitem on a Categorical with a new category (Yes), set the categories first df.loc['200', 'A'] = 'Yes'

type error cannot setitem on categorical with new category

We used the pandas.Categorical class for the A column.

The class is used to represent categorical variables.

Categoricals only take on a limited, and usually fixed, number of possible values (categories).

All values of the Categorical are either in categories (the second argument the pandas.Categorical() class takes) or are np.nan.

Trying to assign values outside of categories raises an error.

# Use the Series.map() method to solve the error

One way to solve the error is to use the Series.map() method instead.

main.py
import pandas as pd df = pd.DataFrame({ 'A': [100, 0] }) print(df) df['A'] = pd.Categorical(df['A']) df['A'] = df['A'].map({100: 'Yes', 0: 'No'}) print('-' * 50) print(df)
The code for this article is available on GitHub

Running the code sample produces the following output.

shell
A 0 100 1 0 -------------------------------------------------- A 0 Yes 1 No

using series map method to solve the error

The Series.map() method maps the values of the Series according to an input mapping (or a function).

We passed a dictionary containing the previous row values and the new row values to Series.map().

main.py
df['A'] = df['A'].map({100: 'Yes', 0: 'No'})

# Using the cat.rename_categories() method to solve the error

You can also use the Series.cat.rename_categories() method to solve the error.

main.py
import pandas as pd df = pd.DataFrame({ 'A': [100, 0] }) print(df) df['A'] = pd.Categorical(df['A']) df['A'] = df['A'].cat.rename_categories( {100: 'Yes', 0: 'No'} ) print('-' * 50) print(df)
The code for this article is available on GitHub

Running the code sample produces the following output.

shell
A 0 100 1 0 -------------------------------------------------- A 0 Yes 1 No

using cat rename categories method to solve the error

The Series.cat.rename_categories() method returns the Categorical column with the given categories renamed.

We passed a dictionary to the method.

The dictionary stores a mapping from old categories to new ones.

main.py
df['A'] = df['A'].cat.rename_categories( {100: 'Yes', 0: 'No'} )

Categories that are not contained in the mapping are passed through and no errors are raised.

# Using the cat.add_categories() method

If you need to add new categories to the Categorical column, use the Series.cat.add_categorical() method.

main.py
import pandas as pd df = pd.DataFrame({ 'A': [100, 0, None] }) print(df) df['A'] = pd.Categorical(df['A']) df['A'] = df['A'].cat.add_categories('Another') df['A'].fillna('Another', inplace=True) print('-' * 50) print(df)
The code for this article is available on GitHub

Running the code sample produces the following output.

shell
A 0 100.0 1 0.0 2 NaN -------------------------------------------------- A 0 100.0 1 0.0 2 Another

The cat.add_categories() method takes a category or a list of categories and adds them to the Categorical column.

All values of the Categorical are either in categories (the second argument the pandas.Categorical() class takes) or are np.nan.

Trying to assign values outside of categories raises an error.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.