Skip to content

Commit ddd90b0

Browse files
authored
BUG: MultiIndex.get_loc with string key on DatetimeIndex level (#42465)
1 parent f3a6753 commit ddd90b0

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ Missing
233233

234234
MultiIndex
235235
^^^^^^^^^^
236+
- Bug in :meth:`MultiIndex.get_loc` where the first level is a :class:`DatetimeIndex` and a string key is passed (:issue:`42465`)
236237
- Bug in :meth:`MultiIndex.reindex` when passing a ``level`` that corresponds to an ``ExtensionDtype`` level (:issue:`42043`)
237238
-
238239

pandas/core/indexes/multi.py

+2
Original file line numberDiff line numberDiff line change
@@ -3164,10 +3164,12 @@ def convert_indexer(start, stop, step, indexer=indexer, codes=level_codes):
31643164
if level > 0 or self._lexsort_depth == 0:
31653165
# Desired level is not sorted
31663166
if isinstance(idx, slice):
3167+
# test_get_loc_partial_timestamp_multiindex
31673168
locs = (level_codes >= idx.start) & (level_codes < idx.stop)
31683169
return locs
31693170

31703171
locs = np.array(level_codes == idx, dtype=bool, copy=False)
3172+
31713173
if not locs.any():
31723174
# The label is present in self.levels[level] but unused:
31733175
raise KeyError(key)

pandas/tests/indexes/multi/test_partial_indexing.py

+37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import numpy as np
12
import pytest
23

34
from pandas import (
@@ -45,6 +46,42 @@ def test_partial_string_matching_single_index(df):
4546
tm.assert_frame_equal(result, expected)
4647

4748

49+
def test_get_loc_partial_timestamp_multiindex(df):
50+
mi = df.index
51+
key = ("2016-01-01", "a")
52+
loc = mi.get_loc(key)
53+
54+
expected = np.zeros(len(mi), dtype=bool)
55+
expected[[0, 3]] = True
56+
tm.assert_numpy_array_equal(loc, expected)
57+
58+
key2 = ("2016-01-02", "a")
59+
loc2 = mi.get_loc(key2)
60+
expected2 = np.zeros(len(mi), dtype=bool)
61+
expected2[[6, 9]] = True
62+
tm.assert_numpy_array_equal(loc2, expected2)
63+
64+
key3 = ("2016-01", "a")
65+
loc3 = mi.get_loc(key3)
66+
expected3 = np.zeros(len(mi), dtype=bool)
67+
expected3[mi.get_level_values(1).get_loc("a")] = True
68+
tm.assert_numpy_array_equal(loc3, expected3)
69+
70+
key4 = ("2016", "a")
71+
loc4 = mi.get_loc(key4)
72+
expected4 = expected3
73+
tm.assert_numpy_array_equal(loc4, expected4)
74+
75+
# non-monotonic
76+
taker = np.arange(len(mi), dtype=np.intp)
77+
taker[::2] = taker[::-2]
78+
mi2 = mi.take(taker)
79+
loc5 = mi2.get_loc(key)
80+
expected5 = np.zeros(len(mi2), dtype=bool)
81+
expected5[[3, 14]] = True
82+
tm.assert_numpy_array_equal(loc5, expected5)
83+
84+
4885
def test_partial_string_timestamp_multiindex(df):
4986
# GH10331
5087
df_swap = df.swaplevel(0, 1).sort_index()

pandas/tests/indexing/multiindex/test_loc.py

+13
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,19 @@ def test_get_loc_datetime_index():
745745
assert mi.get_loc("2001-01") == slice(0, 31, None)
746746
assert index.get_loc("2001-01") == slice(0, 31, None)
747747

748+
loc = mi[::2].get_loc("2001-01")
749+
expected = index[::2].get_loc("2001-01")
750+
assert loc == expected
751+
752+
loc = mi.repeat(2).get_loc("2001-01")
753+
expected = index.repeat(2).get_loc("2001-01")
754+
assert loc == expected
755+
756+
loc = mi.append(mi).get_loc("2001-01")
757+
expected = index.append(index).get_loc("2001-01")
758+
# TODO: standardize return type for MultiIndex.get_loc
759+
tm.assert_numpy_array_equal(loc.nonzero()[0], expected)
760+
748761

749762
def test_loc_setitem_indexer_differently_ordered():
750763
# GH#34603

0 commit comments

Comments
 (0)