Skip to content

CLN: match standardized dispatch logic in IntegerArray #27830

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

Merged
merged 1 commit into from
Aug 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 26 additions & 22 deletions pandas/core/arrays/integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
is_scalar,
)
from pandas.core.dtypes.dtypes import register_extension_dtype
from pandas.core.dtypes.generic import ABCIndexClass, ABCSeries
from pandas.core.dtypes.generic import ABCDataFrame, ABCIndexClass, ABCSeries
from pandas.core.dtypes.missing import isna, notna

from pandas.core import nanops, ops
Expand Down Expand Up @@ -592,25 +592,29 @@ def _values_for_argsort(self) -> np.ndarray:

@classmethod
def _create_comparison_method(cls, op):
def cmp_method(self, other):
op_name = op.__name__

op_name = op.__name__
mask = None
def cmp_method(self, other):

if isinstance(other, (ABCSeries, ABCIndexClass)):
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
# Rely on pandas to unbox and dispatch to us.
return NotImplemented

other = lib.item_from_zerodim(other)
mask = None

if isinstance(other, IntegerArray):
other, mask = other._data, other._mask

elif is_list_like(other):
other = np.asarray(other)
if other.ndim > 0 and len(self) != len(other):
if other.ndim > 1:
raise NotImplementedError(
"can only perform ops with 1-d structures"
)
if len(self) != len(other):
raise ValueError("Lengths must match to compare")

other = lib.item_from_zerodim(other)

# numpy will show a DeprecationWarning on invalid elementwise
# comparisons, this will raise in the future
with warnings.catch_warnings():
Expand Down Expand Up @@ -683,31 +687,31 @@ def _maybe_mask_result(self, result, mask, other, op_name):

@classmethod
def _create_arithmetic_method(cls, op):
def integer_arithmetic_method(self, other):
op_name = op.__name__

op_name = op.__name__
mask = None
def integer_arithmetic_method(self, other):

if isinstance(other, (ABCSeries, ABCIndexClass)):
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
# Rely on pandas to unbox and dispatch to us.
return NotImplemented

if getattr(other, "ndim", 0) > 1:
raise NotImplementedError("can only perform ops with 1-d structures")
other = lib.item_from_zerodim(other)
mask = None

if isinstance(other, IntegerArray):
other, mask = other._data, other._mask

elif getattr(other, "ndim", None) == 0:
other = other.item()

elif is_list_like(other):
other = np.asarray(other)
if not other.ndim:
other = other.item()
elif other.ndim == 1:
if not (is_float_dtype(other) or is_integer_dtype(other)):
raise TypeError("can only perform ops with numeric values")
if other.ndim > 1:
raise NotImplementedError(
"can only perform ops with 1-d structures"
)
if len(self) != len(other):
Copy link
Contributor

Choose a reason for hiding this comment

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

can you make these elif (future PR ok)

raise ValueError("Lengths must match")
if not (is_float_dtype(other) or is_integer_dtype(other)):
raise TypeError("can only perform ops with numeric values")

else:
if not (is_float(other) or is_integer(other)):
raise TypeError("can only perform ops with numeric values")
Expand Down
16 changes: 13 additions & 3 deletions pandas/tests/arrays/test_integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def test_arith_coerce_scalar(self, data, all_arithmetic_operators):
other = 0.01
self._check_op(s, op, other)

@pytest.mark.parametrize("other", [1.0, 1.0, np.array(1.0), np.array([1.0])])
@pytest.mark.parametrize("other", [1.0, np.array(1.0)])
def test_arithmetic_conversion(self, all_arithmetic_operators, other):
# if we have a float operand we should have a float result
# if that is equal to an integer
Expand All @@ -290,6 +290,15 @@ def test_arithmetic_conversion(self, all_arithmetic_operators, other):
result = op(s, other)
assert result.dtype is np.dtype("float")

def test_arith_len_mismatch(self, all_arithmetic_operators):
# operating with a list-like with non-matching length raises
op = self.get_op_from_name(all_arithmetic_operators)
other = np.array([1.0])

s = pd.Series([1, 2, 3], dtype="Int64")
with pytest.raises(ValueError, match="Lengths must match"):
op(s, other)

@pytest.mark.parametrize("other", [0, 0.5])
def test_arith_zero_dim_ndarray(self, other):
arr = integer_array([1, None, 2])
Expand Down Expand Up @@ -322,8 +331,9 @@ def test_error(self, data, all_arithmetic_operators):
ops(pd.Series(pd.date_range("20180101", periods=len(s))))

# 2d
with pytest.raises(NotImplementedError):
opa(pd.DataFrame({"A": s}))
result = opa(pd.DataFrame({"A": s}))
assert result is NotImplemented

with pytest.raises(NotImplementedError):
opa(np.arange(len(s)).reshape(-1, len(s)))

Expand Down