Skip to content

BUG: Fix comparison between nullable int and string #28945

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 22 commits into from
Dec 10, 2019
Merged
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ ExtensionArray
^^^^^^^^^^^^^^

- Bug in :class:`arrays.PandasArray` when setting a scalar string (:issue:`28118`, :issue:`28150`).
- Bug where nullable integers could not be compared to strings (:issue:`28930`)
-


Expand Down
9 changes: 8 additions & 1 deletion pandas/core/arrays/integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from pandas.core import nanops, ops
from pandas.core.algorithms import take
from pandas.core.arrays import ExtensionArray, ExtensionOpsMixin
from pandas.core.ops import invalid_comparison
from pandas.core.tools.numeric import to_numeric


Expand Down Expand Up @@ -628,7 +629,13 @@ def cmp_method(self, other):
with warnings.catch_warnings():
warnings.filterwarnings("ignore", "elementwise", FutureWarning)
with np.errstate(all="ignore"):
result = op(self._data, other)
method = getattr(
self._data, "__{op_name}__".format(op_name=op_name)
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 change this to a f-string

)
result = method(other)

if result is NotImplemented:
result = invalid_comparison(self._data, other, op)

# nans propagate
if mask is None:
Expand Down
33 changes: 33 additions & 0 deletions pandas/tests/extension/test_integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,39 @@ def check_opname(self, s, op_name, other, exc=None):
def _compare_other(self, s, data, op_name, other):
self.check_opname(s, op_name, other)

@pytest.mark.parametrize("dtype", ["Int64", "Int32", "Int16", "Int8"])
def test_compare_unequal_to_string(self, dtype):
# GH 28930
s = pd.Series([1, None], dtype=dtype)
result = s == "a"
expected = pd.Series([False, False])

self.assert_series_equal(result, expected)

@pytest.mark.parametrize("dtype", ["Int64", "Int32", "Int16", "Int8"])
@pytest.mark.parametrize("op", ["__lt__", "__le__"])
def test_compare_lt(self, dtype, op):
# GH 28930
s = pd.Series([0, 0], dtype=dtype)
method = getattr(s, op)
result = method(1)

expected = pd.Series([True, True])

self.assert_series_equal(result, expected)

@pytest.mark.parametrize("dtype", ["Int64", "Int32", "Int16", "Int8"])
@pytest.mark.parametrize("op", ["__gt__", "__ge__"])
def test_compare_gt(self, dtype, op):
# GH 28930
s = pd.Series([0, 0], dtype=dtype)
method = getattr(s, op)
result = method(-1)

expected = pd.Series([True, True])

self.assert_series_equal(result, expected)


class TestInterface(base.BaseInterfaceTests):
pass
Expand Down