Skip to content

Commit 572476f

Browse files
spacespherejreback
authored andcommitted
BUG: Fix MultiIndex .loc with all numpy arrays (pandas-dev#19772)
1 parent 4871b48 commit 572476f

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

doc/source/whatsnew/v0.23.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ MultiIndex
836836
- Bug in :func:`MultiIndex.get_loc` which would cast boolean to integer labels (:issue:`19086`)
837837
- Bug in :func:`MultiIndex.get_loc` which would fail to locate keys containing ``NaN`` (:issue:`18485`)
838838
- Bug in :func:`MultiIndex.get_loc` in large :class:`MultiIndex`, would fail when levels had different dtypes (:issue:`18520`)
839+
- Bug in indexing where nested indexers having only numpy arrays are handled incorrectly (:issue:`19686`)
839840

840841

841842
I/O

pandas/core/indexing.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -2107,10 +2107,9 @@ def is_nested_tuple(tup, labels):
21072107
if not isinstance(tup, tuple):
21082108
return False
21092109

2110-
# are we nested tuple of: tuple,list,slice
21112110
for i, k in enumerate(tup):
21122111

2113-
if isinstance(k, (tuple, list, slice)):
2112+
if is_list_like(k) or isinstance(k, slice):
21142113
return isinstance(labels, MultiIndex)
21152114

21162115
return False

pandas/tests/indexing/test_loc.py

+42-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import pandas as pd
1010
from pandas.compat import lrange, StringIO
11-
from pandas import Series, DataFrame, Timestamp, date_range, MultiIndex
11+
from pandas import Series, DataFrame, Timestamp, date_range, MultiIndex, Index
1212
from pandas.util import testing as tm
1313
from pandas.tests.indexing.common import Base
1414

@@ -711,3 +711,44 @@ def test_identity_slice_returns_new_object(self):
711711

712712
original_series[:3] = [7, 8, 9]
713713
assert all(sliced_series[:3] == [7, 8, 9])
714+
715+
@pytest.mark.parametrize(
716+
'indexer_type_1',
717+
(list, tuple, set, slice, np.ndarray, Series, Index))
718+
@pytest.mark.parametrize(
719+
'indexer_type_2',
720+
(list, tuple, set, slice, np.ndarray, Series, Index))
721+
def test_loc_getitem_nested_indexer(self, indexer_type_1, indexer_type_2):
722+
# GH #19686
723+
# .loc should work with nested indexers which can be
724+
# any list-like objects (see `pandas.api.types.is_list_like`) or slices
725+
726+
def convert_nested_indexer(indexer_type, keys):
727+
if indexer_type == np.ndarray:
728+
return np.array(keys)
729+
if indexer_type == slice:
730+
return slice(*keys)
731+
return indexer_type(keys)
732+
733+
a = [10, 20, 30]
734+
b = [1, 2, 3]
735+
index = pd.MultiIndex.from_product([a, b])
736+
df = pd.DataFrame(
737+
np.arange(len(index), dtype='int64'),
738+
index=index, columns=['Data'])
739+
740+
keys = ([10, 20], [2, 3])
741+
types = (indexer_type_1, indexer_type_2)
742+
743+
# check indexers with all the combinations of nested objects
744+
# of all the valid types
745+
indexer = tuple(
746+
convert_nested_indexer(indexer_type, k)
747+
for indexer_type, k in zip(types, keys))
748+
749+
result = df.loc[indexer, 'Data']
750+
expected = pd.Series(
751+
[1, 2, 4, 5], name='Data',
752+
index=pd.MultiIndex.from_product(keys))
753+
754+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)