pandas-dev/pandas · error · TypeError

bins argument only works with numeric data.

Error message

bins argument only works with numeric data.

What it means

The value_counts() method accepts a bins parameter to group values into equal-width numeric intervals before counting. Internally it delegates to pd.cut(), which requires numeric data to define interval edges. When the underlying values are non-numeric (strings, datetimes that cannot be binned, categorical, etc.), cut() raises a TypeError that is caught and re-raised with this clearer message.

Solutions

  1. Remove the bins parameter for non-numeric columns: df['col'].value_counts().
  2. Convert the column to numeric first: pd.to_numeric(df['col'], errors='coerce').value_counts(bins=5).
  3. Check the dtype before applying bins: if df['col'].dtype.kind in 'iufc': df['col'].value_counts(bins=5) else: df['col'].value_counts().

Example fix

# before
df['category'].value_counts(bins=5)

# after
df['category'].value_counts()  # no binning for categorical data
Defensive patterns

Strategy: validation

Validate before calling

def safe_value_counts(series, bins=None):
    if bins is not None and series.dtype.kind not in 'iufcb':
        # integer, unsigned, float, complex, boolean
        raise TypeError(
            f"bins requires numeric data, got dtype {series.dtype}"
        )
    return series.value_counts(bins=bins)

Type guard

def is_numeric_for_bins(series) -> bool:
    return series.dtype.kind in 'iufcb'

Try / catch

try:
    result = df['col'].value_counts(bins=5)
except TypeError as e:
    if "bins argument" in str(e):
        result = df['col'].value_counts()  # fall back without bins
    else:
        raise

Prevention

When it happens

Trigger: Calling df['category_column'].value_counts(bins=5) on a string or object-dtype column. Calling Series.value_counts(bins=10) on a boolean or timedelta column that cut() cannot bin. Passing bins to value_counts on categorical data.

Common situations: Applying a generic value_counts(bins=N) template across mixed-type DataFrame columns without checking dtype first. Processing a column that was expected to be numeric but contains string representations of numbers or mixed types. Reusing analysis code from a numeric pipeline on a text-heavy dataset.

Related errors


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

Appendix: 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 3b7651241d)