From 746a10938d12cc1aebcb442794c460ee4a3ff98a Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Sat, 13 Nov 2021 13:49:53 +0100 Subject: [PATCH 1/2] BUG: Using boolean keys to select a column (#44322) --- doc/source/whatsnew/v1.4.0.rst | 2 +- pandas/core/indexing.py | 2 +- pandas/tests/indexing/test_loc.py | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index ee1dd58149451..2cf14545fc04f 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -576,7 +576,7 @@ Indexing - Bug in :meth:`Series.__setitem__` with an integer dtype other than ``int64`` setting with a ``range`` object unnecessarily upcasting to ``int64`` (:issue:`44261`) - Bug in :meth:`Series.__setitem__` with a boolean mask indexer setting a listlike value of length 1 incorrectly broadcasting that value (:issue:`44265`) - Bug in :meth:`DataFrame.loc.__setitem__` and :meth:`DataFrame.iloc.__setitem__` with mixed dtypes sometimes failing to operate in-place (:issue:`44345`) -- +- Bug in :meth:`DataFrame.loc.__getitem__` incorrectly raising ``KeyError`` when selecting a single column with a boolean key (:issue:`44322`). Missing ^^^^^^^ diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 91f1415178471..7d12a27aed84a 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -994,7 +994,7 @@ def _validate_key(self, key, axis: int): # slice of labels (where start-end in labels) # slice of integers (only if in the labels) # boolean not in slice and with boolean index - if isinstance(key, bool) and not is_bool_dtype(self.obj.index): + if isinstance(key, bool) and not is_bool_dtype(self.obj._get_axis(axis)): raise KeyError( f"{key}: boolean label can not be used without a boolean index" ) diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index ed9b5cc0850b9..23c456a543d88 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -178,6 +178,13 @@ def test_column_types_consistent(self): ) tm.assert_frame_equal(df, expected) + def test_loc_getitem_column_boolean_arg(self): + # GH 44322 + df = DataFrame([[1]], columns=Index([False])) + res = df.loc[:, False] + exp = Series([1], name=False) + tm.assert_series_equal(res, exp) + class TestLoc2: # TODO: better name, just separating out things that rely on base class From a9a149a45487f0617e1b6e9353d4ba5a847b2960 Mon Sep 17 00:00:00 2001 From: Dries Schaumont Date: Mon, 15 Nov 2021 06:18:20 +0100 Subject: [PATCH 2/2] Add extra tests. --- pandas/tests/indexing/test_loc.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index 23c456a543d88..181887b9fde03 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -178,12 +178,25 @@ def test_column_types_consistent(self): ) tm.assert_frame_equal(df, expected) - def test_loc_getitem_column_boolean_arg(self): + @pytest.mark.parametrize( + "obj, key, exp", + [ + ( + DataFrame([[1]], columns=Index([False])), + IndexSlice[:, False], + Series([1], name=False), + ), + (Series([1], index=Index([False])), False, [1]), + (DataFrame([[1]], index=Index([False])), False, Series([1], name=False)), + ], + ) + def test_loc_getitem_single_boolean_arg(self, obj, key, exp): # GH 44322 - df = DataFrame([[1]], columns=Index([False])) - res = df.loc[:, False] - exp = Series([1], name=False) - tm.assert_series_equal(res, exp) + res = obj.loc[key] + if isinstance(exp, (DataFrame, Series)): + tm.assert_equal(res, exp) + else: + assert res == exp class TestLoc2: