Issue #3: BUG: round on object columns no longer raises a TypeError #61206 - matifaro/pandas GitHub Wiki

Issue

Issue #61206 was opened in March 31, 2025 by @MT407 and is planned as part of milestone 2.3.

The issue

Due to a bisection point at PR #56767, which aimed to fix the issue #55936, the pd.Series.round() method was changed, intruducing unwanted behavior in 2.2.0. In previous versions, attempting to round a column with "object" dtype would raise a TypeError. In 2.2.3, round now silently returns the same column, without applying any rounding.

Reproducible Example of Bug:

import pandas as pd
df=pd.DataFrame(data=['foo'],columns=['bar'])
df.loc[0,'bar']=0.2
print(df['bar'].round())

Out[4]: 
0    0.2

Expected Behavior:

import pandas as pd
df=pd.DataFrame(data=['foo'],columns=['bar'])
df.loc[0,'bar']=0.2
print(df['bar'].round())

TypeError: loop of ufunc does not support argument 0 of type float which has no callable rint method

Requirements

Pandas is a cross-platform, open-source data analysis library for Python, to use it, one must have a python environment and import pandas with pip install pandas.

Source code files

The round functionality is implemented across these core modules:

  • pandas/core/generic.py: defines base NDFrame methods including round() delegation.
  • pandas/core/series.py: overrides and/or extends NDFrame for Series.round().
  • pandas/core/frame.py: implements DataFrame.round(), delegating per-column.
  • pandas/core/internals/blocks.py: BlockManager and Block-level round() behavior.

Code Fragments:

Old:

def round(self, decimals: int = 0, *args, **kwargs) -> Series:
      nv.validate_round(args, kwargs)
      result = self._values.round(decimals)
      result = self._constructor(result, index=self.index, copy=False).__finalize__(
            self, method="round"
      )
return result

Current Code:

def round(self, decimals: int = 0, *args, **kwargs) -> Series:
      nv.validate_round(args, kwargs)
      new_mgr = self._mgr.round(decimals=decimals, using_cow=using_copy_on_write())
      return self._constructor_from_mgr(new_mgr, axes=new_mgr.axes).__finalize__(
            self, method="round"
      )

Design of the fix

Since the bug was classified as regression, we aim to restore the previous behavior and throw a TypeError when trying to round an "object", however the old error message "loop of ufunc does not support argument 0 of type float which has no callable rint method" resulted from calling a different round method than the one currently in use, that introduced the bug. Since the new one is still the correct one (delegates round to BlockManager), simulating the previous message makes little sence, and we will instead provide a cleared error message.

Fix source code

Round method with an added type check:
pandas/core/series.py

def round(self, decimals: int = 0, *args, **kwargs) -> Series:
    if self.dtype.kind == "O":
        raise TypeError(f"Cannot round Series with dtype {self.dtype}")
    nv.validate_round(args, kwargs)
    new_mgr = self._mgr.round(decimals=decimals)
    return self._constructor_from_mgr(new_mgr, axes=new_mgr.axes).__finalize__(
        self, method="round"
    )

Test for the expected error:
pandas/tests/series/methods/test_round.py

def test_round_object_typeerror(self):
    df = pd.DataFrame({"a": ["foo", 1.23]})
    with pytest.raises(TypeError):
        df["a"].round()

Submit the fix

Currently we haven't submitted this fix yet given that we are still waiting on a response from the head of the collaborators.