From 77fb53a29fdfd634485eb125c28e55692f33ab9e Mon Sep 17 00:00:00 2001 From: arw2019 Date: Sat, 27 Jun 2020 05:24:03 +0000 Subject: [PATCH 1/9] add values.dtype.kind==f branch to array_with_unit_datetime --- pandas/_libs/tslib.pyx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index e4128af62d06d..ac9c4cd524d04 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -227,7 +227,6 @@ def array_with_unit_to_datetime( m = cast_from_unit(None, unit) if is_raise: - # try a quick conversion to i8 # if we have nulls that are not type-compat # then need to iterate @@ -240,9 +239,17 @@ def array_with_unit_to_datetime( fvalues = iresult.astype('f8') * m need_to_iterate = False + # GH20445 + if values.dtype.kind == "f": + fresult = values.astype('f8', casting='same_kind', copy=False) + # fill by comparing to NPY_NAT constant + mask = fresult == NPY_NAT + fresult[mask] = 0.0 + fvalues = fvalues.astype('f8') * m # FIXME: this line segfaults rn + need_to_iterate = False + # check the bounds if not need_to_iterate: - if ((fvalues < Timestamp.min.value).any() or (fvalues > Timestamp.max.value).any()): raise OutOfBoundsDatetime(f"cannot convert input with unit '{unit}'") @@ -410,7 +417,6 @@ cpdef array_to_datetime( float offset_seconds, tz_offset set out_tzoffset_vals = set() bint string_to_dts_failed - # specify error conditions assert is_raise or is_ignore or is_coerce From 5104bed99dd090ea8618ee19528a346671837320 Mon Sep 17 00:00:00 2001 From: arw2019 Date: Mon, 29 Jun 2020 01:06:23 +0000 Subject: [PATCH 2/9] revert pandas/_libs/tslib.pyx --- pandas/_libs/tslib.pyx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index ac9c4cd524d04..e4128af62d06d 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -227,6 +227,7 @@ def array_with_unit_to_datetime( m = cast_from_unit(None, unit) if is_raise: + # try a quick conversion to i8 # if we have nulls that are not type-compat # then need to iterate @@ -239,17 +240,9 @@ def array_with_unit_to_datetime( fvalues = iresult.astype('f8') * m need_to_iterate = False - # GH20445 - if values.dtype.kind == "f": - fresult = values.astype('f8', casting='same_kind', copy=False) - # fill by comparing to NPY_NAT constant - mask = fresult == NPY_NAT - fresult[mask] = 0.0 - fvalues = fvalues.astype('f8') * m # FIXME: this line segfaults rn - need_to_iterate = False - # check the bounds if not need_to_iterate: + if ((fvalues < Timestamp.min.value).any() or (fvalues > Timestamp.max.value).any()): raise OutOfBoundsDatetime(f"cannot convert input with unit '{unit}'") @@ -417,6 +410,7 @@ cpdef array_to_datetime( float offset_seconds, tz_offset set out_tzoffset_vals = set() bint string_to_dts_failed + # specify error conditions assert is_raise or is_ignore or is_coerce From 6338c59b68e7703e4e447bdecd9f49183d66f836 Mon Sep 17 00:00:00 2001 From: arw2019 Date: Sat, 25 Jul 2020 14:07:49 +0000 Subject: [PATCH 3/9] throw error in xs when passed pd.IndexSlice --- pandas/core/generic.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 42d02f37508fc..e7086a728f092 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -3477,7 +3477,10 @@ class animal locomotion index = self.index if isinstance(index, MultiIndex): - loc, new_index = self.index.get_loc_level(key, drop_level=drop_level) + try: + loc, new_index = self.index.get_loc_level(key, drop_level=drop_level) + except TypeError: + raise TypeError(f"Expected label or tuple of labels, got {key}") else: loc = self.index.get_loc(key) From d0118c1e3687f21e3ecdf074e48eeed996069f03 Mon Sep 17 00:00:00 2001 From: arw2019 Date: Sat, 25 Jul 2020 14:08:17 +0000 Subject: [PATCH 4/9] added xfail test for xs with pd.IndexSlice argument --- pandas/tests/test_multilevel.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pandas/tests/test_multilevel.py b/pandas/tests/test_multilevel.py index 1ba73292dc0b4..96356ce1531ae 100644 --- a/pandas/tests/test_multilevel.py +++ b/pandas/tests/test_multilevel.py @@ -1258,6 +1258,16 @@ def test_level_with_tuples(self): tm.assert_frame_equal(result, expected) tm.assert_frame_equal(result2, expected) + # GH 35301 + msg = ( + "Expected label or tuple of labels, got " + r"\(\('foo', 'qux', 0\), slice\(None, None, None\)\)" + ) + with pytest.raises(TypeError, match=msg): + frame.xs(pd.IndexSlice[("foo", "qux", 0), :]) + with pytest.raises(TypeError, match=msg): + series.xs(pd.IndexSlice[("foo", "qux", 0), :]) + index = MultiIndex( levels=[[("foo", "bar"), ("foo", "baz"), ("foo", "qux")], [0, 1]], codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]], From 60c919ccab424d938d7063b1b4f64d6e4c9cdfe9 Mon Sep 17 00:00:00 2001 From: arw2019 Date: Wed, 29 Jul 2020 19:17:30 +0000 Subject: [PATCH 5/9] added release note --- doc/source/whatsnew/v1.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 6f173cb2fce12..b4b29c859e03d 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -115,7 +115,7 @@ Missing MultiIndex ^^^^^^^^^^ -- +- Bug in `DataFrame.xs` when used with `IndexSlice` raises ``TypeError`` with message `Expected label or tuple of labels` (:issue:`35301`) - I/O From e04b5c18430851e52bfe16ca18d1cb7dc201de78 Mon Sep 17 00:00:00 2001 From: arw2019 Date: Tue, 4 Aug 2020 01:13:40 +0000 Subject: [PATCH 6/9] fix whatsnew --- doc/source/whatsnew/v1.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index b4b29c859e03d..433812e51c567 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -115,7 +115,7 @@ Missing MultiIndex ^^^^^^^^^^ -- Bug in `DataFrame.xs` when used with `IndexSlice` raises ``TypeError`` with message `Expected label or tuple of labels` (:issue:`35301`) +- Bug in :meth:`DataFrame.xs` when used with :class:`IndexSlice` raises ``TypeError`` with message `Expected label or tuple of labels` (:issue:`35301`) - I/O From dc8c579013e2a1d95db7a6cf6be7e3101b8a8774 Mon Sep 17 00:00:00 2001 From: arw2019 Date: Tue, 4 Aug 2020 01:14:57 +0000 Subject: [PATCH 7/9] rewrote error capture --- pandas/core/generic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index e7086a728f092..736ca08c6eda8 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -3479,8 +3479,8 @@ class animal locomotion if isinstance(index, MultiIndex): try: loc, new_index = self.index.get_loc_level(key, drop_level=drop_level) - except TypeError: - raise TypeError(f"Expected label or tuple of labels, got {key}") + except TypeError as e: + raise TypeError(f"Expected label or tuple of labels, got {key}") from e else: loc = self.index.get_loc(key) From fc9c4cdee96676f763d80204e8f9da81262b85e9 Mon Sep 17 00:00:00 2001 From: arw2019 Date: Tue, 4 Aug 2020 01:15:23 +0000 Subject: [PATCH 8/9] created separate test --- pandas/tests/test_multilevel.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/pandas/tests/test_multilevel.py b/pandas/tests/test_multilevel.py index 96356ce1531ae..406d609458b16 100644 --- a/pandas/tests/test_multilevel.py +++ b/pandas/tests/test_multilevel.py @@ -1258,16 +1258,6 @@ def test_level_with_tuples(self): tm.assert_frame_equal(result, expected) tm.assert_frame_equal(result2, expected) - # GH 35301 - msg = ( - "Expected label or tuple of labels, got " - r"\(\('foo', 'qux', 0\), slice\(None, None, None\)\)" - ) - with pytest.raises(TypeError, match=msg): - frame.xs(pd.IndexSlice[("foo", "qux", 0), :]) - with pytest.raises(TypeError, match=msg): - series.xs(pd.IndexSlice[("foo", "qux", 0), :]) - index = MultiIndex( levels=[[("foo", "bar"), ("foo", "baz"), ("foo", "qux")], [0, 1]], codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]], @@ -1290,6 +1280,26 @@ def test_level_with_tuples(self): tm.assert_frame_equal(result, expected) tm.assert_frame_equal(result2, expected) + def test_xs_with_IndexSlice(self): + # GH 35301 + + index = MultiIndex( + levels=[[("foo", "bar", 0), ("foo", "baz", 0), ("foo", "qux", 0)], [0, 1]], + codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]], + ) + + series = Series(np.random.randn(6), index=index) + frame = DataFrame(np.random.randn(6, 4), index=index) + + msg = ( + "Expected label or tuple of labels, got " + r"\(\('foo', 'qux', 0\), slice\(None, None, None\)\)" + ) + with pytest.raises(TypeError, match=msg): + frame.xs(pd.IndexSlice[("foo", "qux", 0), :]) + with pytest.raises(TypeError, match=msg): + series.xs(pd.IndexSlice[("foo", "qux", 0), :]) + def test_mixed_depth_pop(self): arrays = [ ["a", "top", "top", "routine1", "routine1", "routine2"], From 9ed26542bacfb0b6299c99a1a7bc2db6329d8796 Mon Sep 17 00:00:00 2001 From: arw2019 Date: Fri, 7 Aug 2020 00:47:06 +0000 Subject: [PATCH 9/9] move test to test_xs.py --- pandas/tests/indexing/multiindex/test_xs.py | 23 ++++++++++++++++++++- pandas/tests/test_multilevel.py | 20 ------------------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/pandas/tests/indexing/multiindex/test_xs.py b/pandas/tests/indexing/multiindex/test_xs.py index b807795b9c309..91be1d913001b 100644 --- a/pandas/tests/indexing/multiindex/test_xs.py +++ b/pandas/tests/indexing/multiindex/test_xs.py @@ -1,7 +1,7 @@ import numpy as np import pytest -from pandas import DataFrame, Index, MultiIndex, Series, concat, date_range +from pandas import DataFrame, Index, IndexSlice, MultiIndex, Series, concat, date_range import pandas._testing as tm import pandas.core.common as com @@ -220,6 +220,27 @@ def test_xs_level_series_slice_not_implemented( s[2000, 3:4] +def test_xs_IndexSlice_argument_not_implemented(): + # GH 35301 + + index = MultiIndex( + levels=[[("foo", "bar", 0), ("foo", "baz", 0), ("foo", "qux", 0)], [0, 1]], + codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]], + ) + + series = Series(np.random.randn(6), index=index) + frame = DataFrame(np.random.randn(6, 4), index=index) + + msg = ( + "Expected label or tuple of labels, got " + r"\(\('foo', 'qux', 0\), slice\(None, None, None\)\)" + ) + with pytest.raises(TypeError, match=msg): + frame.xs(IndexSlice[("foo", "qux", 0), :]) + with pytest.raises(TypeError, match=msg): + series.xs(IndexSlice[("foo", "qux", 0), :]) + + def test_series_getitem_multiindex_xs(): # GH6258 dt = list(date_range("20130903", periods=3)) diff --git a/pandas/tests/test_multilevel.py b/pandas/tests/test_multilevel.py index 406d609458b16..1ba73292dc0b4 100644 --- a/pandas/tests/test_multilevel.py +++ b/pandas/tests/test_multilevel.py @@ -1280,26 +1280,6 @@ def test_level_with_tuples(self): tm.assert_frame_equal(result, expected) tm.assert_frame_equal(result2, expected) - def test_xs_with_IndexSlice(self): - # GH 35301 - - index = MultiIndex( - levels=[[("foo", "bar", 0), ("foo", "baz", 0), ("foo", "qux", 0)], [0, 1]], - codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]], - ) - - series = Series(np.random.randn(6), index=index) - frame = DataFrame(np.random.randn(6, 4), index=index) - - msg = ( - "Expected label or tuple of labels, got " - r"\(\('foo', 'qux', 0\), slice\(None, None, None\)\)" - ) - with pytest.raises(TypeError, match=msg): - frame.xs(pd.IndexSlice[("foo", "qux", 0), :]) - with pytest.raises(TypeError, match=msg): - series.xs(pd.IndexSlice[("foo", "qux", 0), :]) - def test_mixed_depth_pop(self): arrays = [ ["a", "top", "top", "routine1", "routine1", "routine2"],