Skip to content

Commit d5eab1b

Browse files
authored
API: Index.__cmp__(Series) return NotImplemented (#61884)
1 parent 3e9237c commit d5eab1b

File tree

6 files changed

+21
-24
lines changed

6 files changed

+21
-24
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ Other API changes
414414
- Index set operations (like union or intersection) will now ignore the dtype of
415415
an empty ``RangeIndex`` or empty ``Index`` with object dtype when determining
416416
the dtype of the resulting Index (:issue:`60797`)
417+
- Comparison operations between :class:`Index` and :class:`Series` now consistently return :class:`Series` regardless of which object is on the left or right (:issue:`36759`)
417418
- Numpy functions like ``np.isinf`` that return a bool dtype when called on a :class:`Index` object now return a bool-dtype :class:`Index` instead of ``np.ndarray`` (:issue:`52676`)
418419

419420
.. ---------------------------------------------------------------------------

pandas/core/ops/common.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,14 @@ def _unpack_zerodim_and_defer(method: F, name: str) -> F:
5656
-------
5757
method
5858
"""
59-
stripped_name = name.removeprefix("__").removesuffix("__")
60-
is_cmp = stripped_name in {"eq", "ne", "lt", "le", "gt", "ge"}
6159

6260
@wraps(method)
6361
def new_method(self, other):
64-
if is_cmp and isinstance(self, ABCIndex) and isinstance(other, ABCSeries):
65-
# For comparison ops, Index does *not* defer to Series
66-
pass
67-
else:
68-
prio = getattr(other, "__pandas_priority__", None)
69-
if prio is not None:
70-
if prio > self.__pandas_priority__:
71-
# e.g. other is DataFrame while self is Index/Series/EA
72-
return NotImplemented
62+
prio = getattr(other, "__pandas_priority__", None)
63+
if prio is not None:
64+
if prio > self.__pandas_priority__:
65+
# e.g. other is DataFrame while self is Index/Series/EA
66+
return NotImplemented
7367

7468
other = item_from_zerodim(other)
7569

pandas/tests/arithmetic/common.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,24 +111,19 @@ def xbox2(x):
111111
return x.astype(bool)
112112
return x
113113

114-
# rev_box: box to use for reversed comparisons
115-
rev_box = xbox
116-
if isinstance(right, Index) and isinstance(left, Series):
117-
rev_box = np.array
118-
119114
result = xbox2(left == right)
120115
expected = xbox(np.zeros(result.shape, dtype=np.bool_))
121116

122117
tm.assert_equal(result, expected)
123118

124119
result = xbox2(right == left)
125-
tm.assert_equal(result, rev_box(expected))
120+
tm.assert_equal(result, xbox(expected))
126121

127122
result = xbox2(left != right)
128123
tm.assert_equal(result, ~expected)
129124

130125
result = xbox2(right != left)
131-
tm.assert_equal(result, rev_box(~expected))
126+
tm.assert_equal(result, xbox(~expected))
132127

133128
msg = "|".join(
134129
[

pandas/tests/arithmetic/test_datetime64.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -770,11 +770,18 @@ def test_dti_cmp_tdi_tzawareness(self, other):
770770

771771
result = dti == other
772772
expected = np.array([False] * 10)
773-
tm.assert_numpy_array_equal(result, expected)
773+
if isinstance(other, Series):
774+
tm.assert_series_equal(result, Series(expected, index=other.index))
775+
else:
776+
tm.assert_numpy_array_equal(result, expected)
774777

775778
result = dti != other
776779
expected = np.array([True] * 10)
777-
tm.assert_numpy_array_equal(result, expected)
780+
if isinstance(other, Series):
781+
tm.assert_series_equal(result, Series(expected, index=other.index))
782+
else:
783+
tm.assert_numpy_array_equal(result, expected)
784+
778785
msg = "Invalid comparison between"
779786
with pytest.raises(TypeError, match=msg):
780787
dti < other

pandas/tests/indexes/multi/test_equivalence.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ def test_equals_op(idx):
6464
with pytest.raises(ValueError, match="Lengths must match"):
6565
index_a == series_b
6666

67-
tm.assert_numpy_array_equal(index_a == series_a, expected1)
68-
tm.assert_numpy_array_equal(index_a == series_c, expected2)
67+
tm.assert_series_equal(index_a == series_a, Series(expected1))
68+
tm.assert_series_equal(index_a == series_c, Series(expected2))
6969

7070
# cases where length is 1 for one of them
7171
with pytest.raises(ValueError, match="Lengths must match"):

pandas/tests/indexes/test_old_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,8 +560,8 @@ def test_equals_op(self, simple_index):
560560
with pytest.raises(ValueError, match=msg):
561561
index_a == series_b
562562

563-
tm.assert_numpy_array_equal(index_a == series_a, expected1)
564-
tm.assert_numpy_array_equal(index_a == series_c, expected2)
563+
tm.assert_series_equal(index_a == series_a, Series(expected1))
564+
tm.assert_series_equal(index_a == series_c, Series(expected2))
565565

566566
# cases where length is 1 for one of them
567567
with pytest.raises(ValueError, match="Lengths must match"):

0 commit comments

Comments
 (0)