pandas-dev/pandas · error · TypeError
Categorical input must be list-like
Error message
Categorical input must be list-like
What it means
Raised in the Categorical constructor when `values` is not list-like (is_list_like returns False). Categoricals wrap a finite enumeration of values, so a single scalar like an int or str cannot form one; pandas requires an iterable of values.
Source
Thrown at pandas/core/arrays/categorical.py:412
def __init__(
self,
values,
categories=None,
ordered=None,
dtype: Dtype | None = None,
copy: bool = True,
) -> None:
dtype = CategoricalDtype._from_values_or_dtype(
values, categories, ordered, dtype
)
# At this point, dtype is always a CategoricalDtype, but
# we may have dtype.categories be None, and we need to
# infer categories in a factorization step further below
if not is_list_like(values):
# GH#38433
raise TypeError("Categorical input must be list-like")
# null_mask indicates missing values we want to exclude from inference.
# This means: only missing values in list-likes (not arrays/ndframes).
null_mask = np.array(False)
# sanitize input
vdtype = getattr(values, "dtype", None)
if isinstance(vdtype, CategoricalDtype):
if dtype.categories is None:
dtype = CategoricalDtype(values.categories, dtype.ordered)
elif isinstance(values, range):
from pandas.core.indexes.range import RangeIndex
values = RangeIndex(values)
elif not isinstance(values, (ABCIndex, ABCSeries, ExtensionArray)):
values = com.convert_to_list_like(values)
if isinstance(values, list) and len(values) == 0:
# By convention, empty lists result in object dtype:View on GitHub (pinned to 71959b8cb9)
Solutions
- Wrap the scalar in a list: `pd.Categorical([value])`.
- Ensure the input is a list/ndarray/Series/Index before passing; guard with `isinstance(values, (list, tuple, np.ndarray, pd.Series))`.
- If the value comes from a DataFrame, pass the column (`df['col']`) rather than `df['col'].iloc[0]`.
Example fix
# before
pd.Categorical('a')
# after
pd.Categorical(['a']) Defensive patterns
Strategy: type-guard
Validate before calling
from pandas.api.types import is_list_like
def to_categorical(values, **kw):
if not is_list_like(values):
values = [values]
import pandas as pd
return pd.Categorical(values, **kw) Type guard
def is_list_like_for_categorical(x) -> bool:
from pandas.api.types import is_list_like
return is_list_like(x) Try / catch
try:
cat = pd.Categorical(value)
except TypeError as e:
if 'must be list-like' in str(e):
cat = pd.Categorical([value])
else:
raise Prevention
- Always pass a sequence (list/tuple/ndarray/Series/Index) to Categorical.
- Validate inputs with is_list_like before construction in dynamic code.
- When selecting a single value, wrap in [ ] or pass the whole column.
When it happens
Trigger: `pd.Categorical(5)`, `pd.Categorical('a')`, or passing any non-iterable object as the first argument. Also when a user accidentally passes a single value where a sequence was intended.
Common situations: Programmatically building a Categorical from a variable that is sometimes a scalar; refactoring code that previously received a list down to a single element without wrapping.
Related errors
- Unordered Categoricals can only compare equality or not
- Categoricals can only be compared if 'categories' are the sa
- Cannot compare a Categorical for op {opname} with type {type
- > 1 ndim Categorical are not supported at this time
- 'values' is not ordered, please explicitly specify the categ
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/4b5e82b2052b894c.
Report an issue: GitHub.