TypeError: Unhashable Type When Using Hue - How to Fix It
Answer
This seaborn error occurs when your hue column contains lists, dicts, or other unhashable types instead of simple values like strings or numbers. Fix it by converting the hue column to a hashable type, or by extracting a single value from complex objects.
Why This Happens
Seaborn uses the hue column to create a legend and group data by color. This requires hashing each unique value. Lists and dicts can't be hashed in Python, so when your column contains these types, seaborn fails. Common causes: JSON data parsed into lists, multi-value columns, or accidentally passing the wrong column.
Solution
The rule: hue columns must contain hashable types (strings, numbers, tuples). Convert lists to tuples or strings, extract values from dicts, or explode multi-value columns into separate rows.
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({
'x': [1, 2, 3, 4],
'y': [10, 20, 30, 40],
'category': [['A', 'B'], ['B', 'C'], ['A'], ['C', 'D']], # lists!
'tags': [{'type': 'a'}, {'type': 'b'}, {'type': 'a'}, {'type': 'b'}] # dicts!
})
# โ Problematic: hue column contains lists
sns.scatterplot(data=df, x='x', y='y', hue='category')
# TypeError: unhashable type: 'list'
# โ
Fixed: convert lists to tuples (hashable)
df['category_tuple'] = df['category'].apply(tuple)
sns.scatterplot(data=df, x='x', y='y', hue='category_tuple')
# โ
Fixed: convert lists to strings
df['category_str'] = df['category'].apply(lambda x: ', '.join(x))
sns.scatterplot(data=df, x='x', y='y', hue='category_str')
# โ
Fixed: use first element only
df['category_first'] = df['category'].apply(lambda x: x[0] if x else None)
sns.scatterplot(data=df, x='x', y='y', hue='category_first')
# โ Problematic: hue column contains dicts
sns.scatterplot(data=df, x='x', y='y', hue='tags')
# TypeError: unhashable type: 'dict'
# โ
Fixed: extract value from dict
df['tag_type'] = df['tags'].apply(lambda x: x.get('type'))
sns.scatterplot(data=df, x='x', y='y', hue='tag_type')
# โ
Debug: check what types are in your column
print(df['category'].apply(type).value_counts())
# <class 'list'> 4
# โ
Debug: find unhashable values
def is_hashable(val):
try:
hash(val)
return True
except TypeError:
return False
unhashable = df['category'].apply(lambda x: not is_hashable(x))
print(df[unhashable])
# โ
For exploding multi-value columns into rows
df_exploded = df.explode('category')
sns.scatterplot(data=df_exploded, x='x', y='y', hue='category')Better Workflow
In Zerve, every block exposes column names, types, and shapes in the Variables tab. You see that 'category' contains lists before you run. Spin up parallel branches to test different fixes: tuple conversion, string join, first element extraction. Zerve runs them simultaneously. Compare results side by side and pick the winner. Fix the dtype, re-run the block, chart updates in seconds. No notebooks to restart, no kernel state to manage.
)
&w=1200&q=75)
&w=1200&q=75)
&w=1200&q=75)