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.