pandas-dev/pandas · error · TypeError

Cannot round dtype as it is non-numeric

Error message

Cannot round dtype {self.dtype} as it is non-numeric

What it means

round() is only defined for numeric dtypes (and boolean, which is passed through unchanged as a fast path via self.dtype._is_boolean). For any other ExtensionArray dtype, self.dtype._is_numeric is False and round raises TypeError rather than silently no-op'ing, so callers learn the operation is meaningless. The implementation then uses round for real/integer kinds and np.round for complex.

Solutions

  1. Restrict rounding to numeric columns: df.select_dtypes(include='number').round(n), or round named numeric columns only.
  2. If you own a custom numeric-like EA, ensure self.dtype._is_numeric returns True so round proceeds.
  3. Skip non-numeric columns before rounding in mixed-dtype frames.

Example fix

// before
df.round(2)  # TypeError: Cannot round dtype string as it is non-numeric

// after
df[['a','b']] = df[['a','b']].round(2)  # only numeric columns
Defensive patterns

Strategy: validation

Validate before calling

if not (arr.dtype._is_numeric or arr.dtype._is_boolean):
    raise TypeError(f'cannot round dtype {arr.dtype}')
out = arr.round(n)

Type guard

def is_roundable_dtype(dtype) -> bool:
    return bool(getattr(dtype, '_is_numeric', False)) or bool(getattr(dtype, '_is_boolean', False))

Try / catch

try:
    out = series.round(2)
except TypeError:
    out = series  # non-numeric; leave unchanged

Prevention

When it happens

Trigger: Calling Series.round / DataFrame.round / arr.round(n) on an ExtensionArray whose dtype is neither numeric nor boolean (e.g. string, categorical, a custom non-numeric EA).

Common situations: Applying df.round(2) to a frame containing string or categorical EA columns. Rounding a custom datetime-like or object EA. A pipeline that rounds the whole frame without selecting numeric columns.

Related errors


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

Appendix: source

Thrown at pandas/core/arrays/base.py:2945

        Series.round : Round values of a Series.

        Notes
        -----
        This is a non-performant default implementation.  Subclasses are
        encouraged to override it to avoid the elementwise loop.

        Examples
        --------
        >>> arr = pd.array([1.234, 5.678, pd.NA], dtype="Float64")
        >>> arr.round(1)
        <FloatingArray>
        [1.2, 5.7, <NA>]
        Length: 3, dtype: Float64
        """
        if self.dtype._is_boolean:
            return self.copy()
        if not self.dtype._is_numeric:
            raise TypeError(f"Cannot round dtype {self.dtype} as it is non-numeric")
        # Python's builtin round on complex emits DeprecationWarning (and
        # raises TypeError in a future Python release); use np.round there.
        round_fn = np.round if self.dtype.kind == "c" else round
        rounded = [
            round_fn(item, decimals) if not item_isna else item
            for item, item_isna in zip(self, self.isna(), strict=True)
        ]
        return type(self)._from_sequence(rounded, dtype=self.dtype)

    def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
        if any(
            isinstance(other, (ABCSeries, ABCIndex, ABCDataFrame)) for other in inputs
        ):
            return NotImplemented

        result = arraylike.maybe_dispatch_ufunc_to_dunder_op(
            self, ufunc, method, *inputs, **kwargs
        )

View on GitHub (pinned to 3b7651241d)