Skip to content
Open
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ Other enhancements
- :meth:`Series.map` can now accept kwargs to pass on to func (:issue:`59814`)
- :meth:`Series.map` now accepts an ``engine`` parameter to allow execution with a third-party execution engine (:issue:`61125`)
- :meth:`Series.rank` and :meth:`DataFrame.rank` with numpy-nullable dtypes preserve ``NA`` values and return ``UInt64`` dtype where appropriate instead of casting ``NA`` to ``NaN`` with ``float64`` dtype (:issue:`62043`)
- :meth:`Series.round` now operates pointwise on columns of object dtype (:issue:`62174`)
- :meth:`Series.str.get_dummies` now accepts a ``dtype`` parameter to specify the dtype of the resulting DataFrame (:issue:`47872`)
- :meth:`pandas.concat` will raise a ``ValueError`` when ``ignore_index=True`` and ``keys`` is not ``None`` (:issue:`59274`)
- :py:class:`frozenset` elements in pandas objects are now natively printed (:issue:`60690`)
Expand Down
19 changes: 16 additions & 3 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import functools
import inspect
import re
from typing import (
Expand Down Expand Up @@ -1503,16 +1504,28 @@ def quantile(
def round(self, decimals: int) -> Self:
"""
Rounds the values.
If the block is not of an integer or float dtype, nothing happens.
This is consistent with DataFrame.round behavior.
(Note: Series.round would raise)
If the block is of object dtype, it will operate pointwise and possibly raise.
Otherwise, if the block is not of an integer or float dtype, nothing happens.

Parameters
----------
decimals: int,
Number of decimal places to round to.
Caller is responsible for validating this
"""
if self.dtype == _dtype_obj:
round_func = functools.partial(round, ndigits=decimals)
try:
values = algos.map_array(self.values, round_func)
except TypeError as err:
raise TypeError("Expected numeric entries for dtype object.") from err

refs = None
if values is self.values:
refs = self.refs

return self.make_block_same_class(values, refs=refs)

if not self.is_numeric or self.is_bool:
return self.copy(deep=False)
# TODO: round only defined on BaseMaskedArray
Expand Down
2 changes: 0 additions & 2 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2514,8 +2514,6 @@ def round(self, decimals: int = 0, *args, **kwargs) -> Series:
dtype: float64
"""
nv.validate_round(args, kwargs)
if self.dtype == "object":
raise TypeError("Expected numeric dtype, got object instead.")
new_mgr = self._mgr.round(decimals=decimals)
return self._constructor_from_mgr(new_mgr, axes=new_mgr.axes).__finalize__(
self, method="round"
Expand Down
11 changes: 7 additions & 4 deletions pandas/tests/series/methods/test_round.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@ def test_round_ea_boolean(self):
tm.assert_series_equal(ser, expected)

def test_round_dtype_object(self):
# GH#61206
ser = Series([0.2], dtype="object")
msg = "Expected numeric dtype, got object instead."
# GH#61206, GH#62174
ser = Series([0.232], dtype="object")
expected = Series([0.2])
tm.assert_series_equal(ser.round(1), expected)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separate line for result = ser.round(1)

ser2 = Series(["bar"], dtype="object")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make this a separate test

msg = "Expected numeric entries for dtype object."
with pytest.raises(TypeError, match=msg):
ser.round()
ser2.round()
Loading