Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExtensionArray.Round method and tests #54582

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1125199
add round abc
andrewgsavage Aug 16, 2023
a4ef563
add round test
andrewgsavage Aug 16, 2023
9f6ebc9
round tests
andrewgsavage Aug 16, 2023
2f0f100
lint
andrewgsavage Aug 16, 2023
241ba6c
lint
andrewgsavage Aug 16, 2023
457290d
Merge branch 'main' into round
andrewgsavage Aug 17, 2023
e2a4168
tests
andrewgsavage Aug 26, 2023
a908700
move methods tests, elementwise rounding
andrewgsavage Sep 4, 2023
fbbfe46
lint
andrewgsavage Sep 5, 2023
15915dc
remove test
andrewgsavage Sep 5, 2023
4167122
Merge branch 'main' into round
andrewgsavage Sep 5, 2023
e31d06a
add default round method
andrewgsavage Sep 6, 2023
bfd36f8
merge main
andrewgsavage Sep 6, 2023
bc4d8c6
remove invert
andrewgsavage Sep 6, 2023
362cd73
typo
andrewgsavage Sep 6, 2023
aa79869
decimal array works now
andrewgsavage Sep 6, 2023
2b694bf
move round to base calss
andrewgsavage Sep 24, 2023
01d1453
move pytest mark into if statement
andrewgsavage Sep 24, 2023
e5d500d
nitpick
andrewgsavage Sep 24, 2023
95d07fa
fix pyarrow round dtypes
andrewgsavage Sep 24, 2023
f28d82f
implement sparsearray round
andrewgsavage Oct 19, 2023
2299134
lint
andrewgsavage Oct 19, 2023
15a7cac
lint
andrewgsavage Oct 19, 2023
ee37b4d
mypy
andrewgsavage Oct 19, 2023
70ebf5a
ignore my py error
andrewgsavage Nov 7, 2023
bda7031
Merge branch 'main' into round
andrewgsavage Nov 7, 2023
e01130d
remove blocks ignore mypyr
andrewgsavage Nov 7, 2023
2e73b6a
Merge branch 'round' of https://github.com/andrewgsavage/pandas into …
andrewgsavage Nov 7, 2023
2e9cddf
revert cast
andrewgsavage Nov 8, 2023
76c9ba7
typerror for non numerics
andrewgsavage Nov 8, 2023
044f0a1
isna
andrewgsavage Nov 8, 2023
770edf3
cast pyarrow
andrewgsavage Nov 9, 2023
85f67b6
Merge branch 'main' into round
andrewgsavage Mar 4, 2024
f3d4520
Update blocks.py
andrewgsavage Mar 4, 2024
398e64b
Update blocks.py
andrewgsavage Mar 4, 2024
b0af597
rounding boolean shouldnt error
andrewgsavage Mar 13, 2024
70b6c89
whatsnew
andrewgsavage Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions pandas/core/arrays/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2337,6 +2337,19 @@ def _add_logical_ops(cls) -> None:
setattr(cls, "__xor__", cls._create_logical_method(operator.xor))
setattr(cls, "__rxor__", cls._create_logical_method(roperator.rxor))

def round(self, decimals: int = 0, *args, **kwargs) -> Self:
andrewgsavage marked this conversation as resolved.
Show resolved Hide resolved
# Implementer note: This is a non-optimized default implementation.
# Implementers are encouraged to override this method to avoid
# elementwise rounding.
if not self.dtype._is_numeric or self.dtype._is_boolean:
raise TypeError(
f"Cannot round {self.dtype} dtype as it is non-numeric or boolean"
)
return self._from_sequence(
andrewgsavage marked this conversation as resolved.
Show resolved Hide resolved
[round(element) if not isna(element) else element for element in self.data],
dtype=self.dtype,
)


class ExtensionScalarOpsMixin(ExtensionOpsMixin):
"""
Expand Down
10 changes: 10 additions & 0 deletions pandas/tests/extension/base/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,3 +704,13 @@ def test_equals(self, data, as_series, box):
def test_equals_same_data_different_object(self, data):
# https://github.com/pandas-dev/pandas/issues/34660
assert pd.Series(data).equals(pd.Series(data))

def test_round(self, data):
if not data.dtype._is_numeric or data.dtype._is_boolean:
pytest.skip("Round is only valid for numeric non-boolean dtypes")
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 test that would raise a TypeError instead?

result = pd.Series(data).round()
expected = pd.Series(
jbrockmendel marked this conversation as resolved.
Show resolved Hide resolved
[round(element) if pd.notna(element) else element for element in data],
dtype=data.dtype,
)
tm.assert_series_equal(result, expected)
15 changes: 15 additions & 0 deletions pandas/tests/extension/test_arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,21 @@ def _get_arith_xfail_marker(self, opname, pa_dtype):

return mark

def test_round(self, data, request):
mark = pytest.mark.xfail(
andrewgsavage marked this conversation as resolved.
Show resolved Hide resolved
# raises=pa.ArrowInvalid,
reason="ArrowArray.round converts dtype to double",
)
if (
pa.types.is_float32(data.dtype.pyarrow_dtype)
or pa.types.is_float64(data.dtype.pyarrow_dtype)
or pa.types.is_decimal(data.dtype.pyarrow_dtype)
):
mark = None
if mark is not None:
request.node.add_marker(mark)
super().test_round(data)

def test_arith_series_with_scalar(self, data, all_arithmetic_operators, request):
pa_dtype = data.dtype.pyarrow_dtype

Expand Down
4 changes: 4 additions & 0 deletions pandas/tests/extension/test_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ def test_insert_invalid(self, data, invalid_scalar):
# NumpyExtensionArray[object] can hold anything, so skip
super().test_insert_invalid(data, invalid_scalar)

@pytest.mark.xfail(reason="NumpyExtensionArray.round is not implemented.")
def test_round(self, data):
super().test_round(data)


class TestArithmetics(BaseNumPyTests, base.BaseArithmeticOpsTests):
divmod_exc = None
Expand Down
4 changes: 4 additions & 0 deletions pandas/tests/extension/test_sparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ def test_map_raises(self, data, na_action):
with pytest.raises(ValueError, match=msg):
data.map(lambda x: np.nan, na_action=na_action)

@pytest.mark.xfail(reason="SparseArray.round not implemented.")
Copy link
Member

Choose a reason for hiding this comment

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

why doesnt the base class implementation work here?

def test_round(self, data):
super().test_round(data)


class TestCasting(BaseSparseTests, base.BaseCastingTests):
@pytest.mark.xfail(raises=TypeError, reason="no sparse StringDtype")
Expand Down