Skip to content

Commit 04ab615

Browse files
committed
BUG: PeriodEngine doesn't work (#29038)
1 parent f03ed62 commit 04ab615

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

pandas/_libs/index.pyx

+40-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ from pandas._libs.hashtable cimport HashTable
2525
from pandas._libs import algos, hashtable as _hash
2626
from pandas._libs.tslibs import Timestamp, Timedelta, period as periodlib
2727
from pandas._libs.missing import checknull
28+
from pandas._libs.tslibs.util cimport is_period_object
29+
2830

2931
cdef int64_t NPY_NAT = util.get_nat()
3032

@@ -498,7 +500,7 @@ cdef class TimedeltaEngine(DatetimeEngine):
498500
cdef class PeriodEngine(Int64Engine):
499501

500502
cdef _get_index_values(self):
501-
return super(PeriodEngine, self).vgetter()
503+
return super(PeriodEngine, self).vgetter().view('i8')
502504

503505
cpdef _call_map_locations(self, values):
504506
super(PeriodEngine, self)._call_map_locations(values.view('i8'))
@@ -537,6 +539,43 @@ cdef class PeriodEngine(Int64Engine):
537539

538540
return super(PeriodEngine, self).get_indexer_non_unique(ordinal_array)
539541

542+
cpdef get_loc(self, object key):
543+
cdef:
544+
int64_t loc
545+
if is_definitely_invalid_key(key):
546+
raise TypeError("'{val}' is an invalid key".format(val=key))
547+
548+
ordinal = key.ordinal if is_period_object(key) else key
549+
self._ordinal_check_type(key, ordinal)
550+
551+
if self.over_size_threshold and self.is_monotonic_increasing:
552+
if not self.is_unique:
553+
return self._get_loc_duplicates(key)
554+
555+
values = self._get_index_values()
556+
557+
try:
558+
loc = values.searchsorted(ordinal, side='left')
559+
except TypeError:
560+
raise KeyError(key)
561+
562+
if loc == len(values) or values[loc] != ordinal:
563+
raise KeyError(key)
564+
return loc
565+
566+
self._ensure_mapping_populated()
567+
if not self.unique:
568+
return self._get_loc_duplicates(ordinal)
569+
570+
try:
571+
return self.mapping.get_item(ordinal)
572+
except KeyError:
573+
raise KeyError(key)
574+
575+
cdef inline _ordinal_check_type(self, object key, ordinal):
576+
if not util.is_integer_object(ordinal):
577+
raise KeyError(key)
578+
540579

541580
cpdef convert_scalar(ndarray arr, object value):
542581
# we don't turn integers

pandas/tests/indexes/period/test_indexing.py

+10
Original file line numberDiff line numberDiff line change
@@ -685,3 +685,13 @@ def test_period_index_indexer(self):
685685
tm.assert_frame_equal(df, df.loc[list(idx)])
686686
tm.assert_frame_equal(df.iloc[0:5], df.loc[idx[0:5]])
687687
tm.assert_frame_equal(df, df.loc[list(idx)])
688+
689+
def test_period_engine_get_loc_accept_period(self):
690+
# issue 29038
691+
idx = pd.period_range(start=2010, end=2019, freq="A")
692+
assert idx._engine.get_loc(Period(2015)) == 5
693+
694+
with pytest.raises(KeyError, match=r"Period\('2020', 'A-DEC'\)"):
695+
idx._engine.get_loc(Period(2020))
696+
697+
assert idx._engine.get_loc(Period(2018).ordinal) == 8

0 commit comments

Comments
 (0)