From 5ca6f5691be0bc14de21851afe2bdec1e4850f3c Mon Sep 17 00:00:00 2001 From: Maoyuan Liu Date: Thu, 28 Apr 2016 15:47:49 +1000 Subject: [PATCH 1/3] BUG: .isin(...) now coerces sets to lists --- pandas/core/algorithms.py | 2 ++ pandas/core/common.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 323cbe8e93b78..6f822b82a5850 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -113,6 +113,8 @@ def isin(comps, values): raise TypeError("only list-like objects are allowed to be passed" " to isin(), you passed a " "[{0}]".format(type(values).__name__)) + if com.is_set_like(values): + values = list(values) # GH11232 # work-around for numpy < 1.8 and comparisions on py3 diff --git a/pandas/core/common.py b/pandas/core/common.py index 14c95e01882a2..0dcc8a17292d4 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -1765,6 +1765,10 @@ def is_list_like(arg): not isinstance(arg, compat.string_and_binary_types)) +def is_set_like(arg): + return (is_list_like(arg) and not hasattr(arg, '__getitem__')) + + def is_dict_like(arg): return hasattr(arg, '__getitem__') and hasattr(arg, 'keys') From 20dafeb2b98fc62d33793ebb85a70627fe5551d7 Mon Sep 17 00:00:00 2001 From: Maoyuan Liu Date: Thu, 28 Apr 2016 16:00:24 +1000 Subject: [PATCH 2/3] BUG: added tests for isin(...) sets --- pandas/tests/series/test_analytics.py | 3 +++ pandas/tests/test_common.py | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index af648d34637df..b8e6bf2c05910 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -1118,6 +1118,9 @@ def test_isin_with_i8(self): result = s.isin([np.datetime64(s[1])]) assert_series_equal(result, expected2) + result = s.isin(set(s[0:2])) + assert_series_equal(result, expected) + # timedelta64[ns] s = Series(pd.to_timedelta(lrange(5), unit='d')) result = s.isin(s[0:2]) diff --git a/pandas/tests/test_common.py b/pandas/tests/test_common.py index 9fe0d3c569ae0..050849fc9b512 100644 --- a/pandas/tests/test_common.py +++ b/pandas/tests/test_common.py @@ -571,6 +571,18 @@ def test_is_list_like(): assert not com.is_list_like(f) +def test_is_set_like(): + passes = (set([1, 'a']), frozenset([1, 'a'])) + fails = ([], [1], (1, ), (1, 2), {'a': 1}, Series([1]), Series([]), + Series(['a']).str, 1, '2', object()) + + for p in passes: + assert com.is_set_like(p) + + for f in fails: + assert not com.is_set_like(f) + + def test_is_dict_like(): passes = [{}, {'A': 1}, pd.Series([1])] fails = ['1', 1, [1, 2], (1, 2), range(2), pd.Index([1])] From 3499486adcdc7e45e28996f0dcbeeaa416bb09c7 Mon Sep 17 00:00:00 2001 From: Maoyuan Liu Date: Fri, 29 Apr 2016 11:00:11 +1000 Subject: [PATCH 3/3] BUG: removes com.is_set_like, improved tests for algo.isin(...) --- pandas/core/algorithms.py | 2 +- pandas/core/common.py | 4 ---- pandas/tests/test_algos.py | 20 ++++++++++++++++++++ pandas/tests/test_common.py | 12 ------------ 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 6f822b82a5850..d40d6f2e4134d 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -113,7 +113,7 @@ def isin(comps, values): raise TypeError("only list-like objects are allowed to be passed" " to isin(), you passed a " "[{0}]".format(type(values).__name__)) - if com.is_set_like(values): + if not isinstance(values, np.ndarray): values = list(values) # GH11232 diff --git a/pandas/core/common.py b/pandas/core/common.py index 0dcc8a17292d4..14c95e01882a2 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -1765,10 +1765,6 @@ def is_list_like(arg): not isinstance(arg, compat.string_and_binary_types)) -def is_set_like(arg): - return (is_list_like(arg) and not hasattr(arg, '__getitem__')) - - def is_dict_like(arg): return hasattr(arg, '__getitem__') and hasattr(arg, 'keys') diff --git a/pandas/tests/test_algos.py b/pandas/tests/test_algos.py index 68864306525dc..c6e7fa350d47c 100644 --- a/pandas/tests/test_algos.py +++ b/pandas/tests/test_algos.py @@ -345,6 +345,10 @@ def test_basic(self): expected = np.array([True, False]) tm.assert_numpy_array_equal(result, expected) + result = algos.isin(pd.Series([1, 2]), set([1])) + expected = np.array([True, False]) + tm.assert_numpy_array_equal(result, expected) + result = algos.isin(['a', 'b'], ['a']) expected = np.array([True, False]) tm.assert_numpy_array_equal(result, expected) @@ -353,6 +357,10 @@ def test_basic(self): expected = np.array([True, False]) tm.assert_numpy_array_equal(result, expected) + result = algos.isin(pd.Series(['a', 'b']), set(['a'])) + expected = np.array([True, False]) + tm.assert_numpy_array_equal(result, expected) + result = algos.isin(['a', 'b'], [1]) expected = np.array([False, False]) tm.assert_numpy_array_equal(result, expected) @@ -366,11 +374,23 @@ def test_basic(self): expected = np.array([True, True, False]) tm.assert_numpy_array_equal(result, expected) + result = algos.isin(arr, set(arr[0:2])) + expected = np.array([True, True, False]) + tm.assert_numpy_array_equal(result, expected) + arr = pd.timedelta_range('1 day', periods=3).values result = algos.isin(arr, [arr[0]]) expected = np.array([True, False, False]) tm.assert_numpy_array_equal(result, expected) + result = algos.isin(arr, arr[0:2]) + expected = np.array([True, True, False]) + tm.assert_numpy_array_equal(result, expected) + + result = algos.isin(arr, set(arr[0:2])) + expected = np.array([True, True, False]) + tm.assert_numpy_array_equal(result, expected) + def test_large(self): s = pd.date_range('20000101', periods=2000000, freq='s').values diff --git a/pandas/tests/test_common.py b/pandas/tests/test_common.py index 050849fc9b512..9fe0d3c569ae0 100644 --- a/pandas/tests/test_common.py +++ b/pandas/tests/test_common.py @@ -571,18 +571,6 @@ def test_is_list_like(): assert not com.is_list_like(f) -def test_is_set_like(): - passes = (set([1, 'a']), frozenset([1, 'a'])) - fails = ([], [1], (1, ), (1, 2), {'a': 1}, Series([1]), Series([]), - Series(['a']).str, 1, '2', object()) - - for p in passes: - assert com.is_set_like(p) - - for f in fails: - assert not com.is_set_like(f) - - def test_is_dict_like(): passes = [{}, {'A': 1}, pd.Series([1])] fails = ['1', 1, [1, 2], (1, 2), range(2), pd.Index([1])]