Skip to content

Commit 152b3f8

Browse files
jbrockmendelPingviinituutti
authored andcommitted
Have Categorical ops defer to DataFrame; broken off of pandas-dev#24282 (pandas-dev#24630)
1 parent f349d07 commit 152b3f8

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

doc/source/whatsnew/v0.24.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,7 @@ Categorical
14211421
- Bug in many methods of the ``.str``-accessor, which always failed on calling the ``CategoricalIndex.str`` constructor (:issue:`23555`, :issue:`23556`)
14221422
- Bug in :meth:`Series.where` losing the categorical dtype for categorical data (:issue:`24077`)
14231423
- Bug in :meth:`Categorical.apply` where ``NaN`` values could be handled unpredictably. They now remain unchanged (:issue:`24241`)
1424+
- Bug in :class:`Categorical` comparison methods incorrectly raising ``ValueError`` when operating against a :class:`DataFrame` (:issue:`24630`)
14241425

14251426
Datetimelike
14261427
^^^^^^^^^^^^

pandas/core/arrays/categorical.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
is_timedelta64_dtype)
2424
from pandas.core.dtypes.dtypes import CategoricalDtype
2525
from pandas.core.dtypes.generic import (
26-
ABCCategoricalIndex, ABCIndexClass, ABCSeries)
26+
ABCCategoricalIndex, ABCDataFrame, ABCIndexClass, ABCSeries)
2727
from pandas.core.dtypes.inference import is_hashable
2828
from pandas.core.dtypes.missing import isna, notna
2929

@@ -59,9 +59,11 @@ def f(self, other):
5959
# results depending whether categories are the same or not is kind of
6060
# insane, so be a bit stricter here and use the python3 idea of
6161
# comparing only things of equal type.
62-
if isinstance(other, ABCSeries):
62+
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
6363
return NotImplemented
6464

65+
other = lib.item_from_zerodim(other)
66+
6567
if not self.ordered:
6668
if op in ['__lt__', '__gt__', '__le__', '__ge__']:
6769
raise TypeError("Unordered Categoricals can only compare "
@@ -105,7 +107,6 @@ def f(self, other):
105107
#
106108
# With cat[0], for example, being ``np.int64(1)`` by the time it gets
107109
# into this function would become ``np.array(1)``.
108-
other = lib.item_from_zerodim(other)
109110
if is_scalar(other):
110111
if other in self.categories:
111112
i = self.categories.get_loc(other)

pandas/tests/arrays/categorical/test_operators.py

+26
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# -*- coding: utf-8 -*-
2+
import operator
23

34
import numpy as np
45
import pytest
@@ -113,9 +114,34 @@ def test_comparisons(self):
113114
res = cat_rev > "b"
114115
tm.assert_numpy_array_equal(res, exp)
115116

117+
# check that zero-dim array gets unboxed
118+
res = cat_rev > np.array("b")
119+
tm.assert_numpy_array_equal(res, exp)
120+
116121

117122
class TestCategoricalOps(object):
118123

124+
def test_compare_frame(self):
125+
# GH#24282 check that Categorical.__cmp__(DataFrame) defers to frame
126+
data = ["a", "b", 2, "a"]
127+
cat = Categorical(data)
128+
129+
df = DataFrame(cat)
130+
131+
for op in [operator.eq, operator.ne, operator.ge,
132+
operator.gt, operator.le, operator.lt]:
133+
with pytest.raises(ValueError):
134+
# alignment raises unless we transpose
135+
op(cat, df)
136+
137+
result = cat == df.T
138+
expected = DataFrame([[True, True, True, True]])
139+
tm.assert_frame_equal(result, expected)
140+
141+
result = cat[::-1] != df.T
142+
expected = DataFrame([[False, True, True, False]])
143+
tm.assert_frame_equal(result, expected)
144+
119145
def test_datetime_categorical_comparison(self):
120146
dt_cat = Categorical(date_range('2014-01-01', periods=3), ordered=True)
121147
tm.assert_numpy_array_equal(dt_cat > dt_cat[0],

0 commit comments

Comments
 (0)