pandas-dev/pandas · error · TypeError

bins argument only works with numeric data.

Error message

bins argument only works with numeric data.

What it means

Raised by value_counts_internal when bins is provided but the data cannot be binned. The bins path calls pandas.cut on the values; if cut raises TypeError (non-numeric data such as strings/datetimes that cut cannot handle), pandas re-raises this clearer message. Binning requires numeric data.

Source

Thrown at pandas/core/algorithms.py:1021

        DatetimeIndex,
        Index,
        Series,
        TimedeltaIndex,
    )

    index_name = getattr(values, "name", None)
    name = "proportion" if normalize else "count"

    if bins is not None:
        from pandas.core.reshape.tile import cut

        if isinstance(values, Series):
            values = values._values

        try:
            ii = cut(values, bins, include_lowest=True)
        except TypeError as err:
            raise TypeError("bins argument only works with numeric data.") from err

        # count, remove nulls (from the index), and but the bins
        result = ii.value_counts(dropna=dropna)
        result.name = name
        result = result[result.index.notna()]
        result.index = result.index.astype("interval")
        result = result.sort_index()

        # if we are dropna and we have NO values
        if dropna and (result._values == 0).all():
            result = result.iloc[0:0]

        # normalizing is by len of all (regardless of dropna)
        normalize_denominator = len(ii)

    else:
        normalize_denominator = None
        if is_extension_array_dtype(values):

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Convert the data to numeric first: pd.to_numeric(s, errors='coerce').
  2. Drop bins= for categorical/string data and use plain value_counts.
  3. Restrict the bins call to numeric columns (select_dtypes(include='number')).

Example fix

# before
s = pd.Series(['1', '2', '3', '4'])
s.value_counts(bins=2)
# after
pd.to_numeric(s, errors='coerce').value_counts(bins=2)
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

def value_counts_binned(s, bins):
    if not pd.api.types.is_numeric_dtype(s):
        s = pd.to_numeric(s, errors='coerce')
    return s.value_counts(bins=bins)

Type guard

import pandas as pd

def is_binnable(s) -> bool:
    return pd.api.types.is_numeric_dtype(s)

Try / catch

try:
    return s.value_counts(bins=5)
except TypeError:
    return pd.to_numeric(s, errors='coerce').value_counts(bins=5)

Prevention

When it happens

Trigger: s.value_counts(bins=5) where s is object/string/categorical non-numeric; df.value_counts(bins=...) on non-numeric columns; calling value_counts with bins on a boolean object array.

Common situations: Applying a generic value_counts(bins=N) helper to a DataFrame across all columns without filtering dtypes; data ingestion that left numeric columns as object dtype strings.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/0e136acb57f1ae64. Report an issue: GitHub.