Skip to content

Commit 23f4a50

Browse files
committed
BUG: Create PeriodEngine
1 parent 27bbea7 commit 23f4a50

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

pandas/_libs/index.pyx

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ from tslib cimport _to_i8
1717

1818
from hashtable cimport HashTable
1919

20-
from pandas._libs import algos, hashtable as _hash
20+
from pandas._libs import algos, period as periodlib, hashtable as _hash
2121
from pandas._libs.tslib import Timestamp, Timedelta
2222
from datetime import datetime, timedelta
2323

@@ -270,13 +270,16 @@ cdef class IndexEngine:
270270

271271
values = self._get_index_values()
272272
self.mapping = self._make_hash_table(len(values))
273-
self.mapping.map_locations(values)
273+
self._call_map_locations(values)
274274

275275
if len(self.mapping) == len(values):
276276
self.unique = 1
277277

278278
self.need_unique_check = 0
279279

280+
cpdef _call_map_locations(self, values):
281+
self.mapping.map_locations(values)
282+
280283
def clear_mapping(self):
281284
self.mapping = None
282285
self.need_monotonic_check = 1
@@ -490,6 +493,76 @@ cdef class TimedeltaEngine(DatetimeEngine):
490493
cdef _get_box_dtype(self):
491494
return 'm8[ns]'
492495

496+
497+
cdef class PeriodEngine(Int64Engine):
498+
499+
cdef _get_index_values(self):
500+
return self.vgetter()
501+
502+
cpdef _call_map_locations(self, values):
503+
super(PeriodEngine, self)._call_map_locations(values.view('i8'))
504+
505+
def _call_monotonic(self, values):
506+
return super(PeriodEngine, self)._call_monotonic(values.view('i8'))
507+
508+
cdef _maybe_get_bool_indexer(self, object val):
509+
cdef:
510+
ndarray[uint8_t, cast=True] indexer
511+
ndarray[int64_t] values
512+
int count = 0
513+
Py_ssize_t i, n
514+
int last_true
515+
516+
if not util.is_integer_object(val):
517+
raise KeyError(val)
518+
519+
values = self._get_index_values().view('i8')
520+
n = len(values)
521+
522+
result = np.empty(n, dtype=bool)
523+
indexer = result.view(np.uint8)
524+
525+
for i in range(n):
526+
if values[i] == val:
527+
count += 1
528+
indexer[i] = 1
529+
last_true = i
530+
else:
531+
indexer[i] = 0
532+
533+
if count == 0:
534+
raise KeyError(val)
535+
if count == 1:
536+
return last_true
537+
538+
return result
539+
540+
def get_indexer(self, values):
541+
cdef ndarray[int64_t, ndim=1] ordinals
542+
543+
self._ensure_mapping_populated()
544+
ordinals = periodlib.extract_ordinals(values, self.vgetter().freq)
545+
return self.mapping.lookup(ordinals)
546+
547+
def get_pad_indexer(self, other, limit=None):
548+
ordinal = periodlib.extract_ordinals(other, self.vgetter().freq)
549+
550+
return algos.pad_int64(self._get_index_values(),
551+
np.asarray(ordinal), limit=limit)
552+
553+
def get_backfill_indexer(self, other, limit=None):
554+
ordinal = periodlib.extract_ordinals(other, self.vgetter().freq)
555+
556+
return algos.backfill_int64(self._get_index_values(),
557+
np.asarray(ordinal), limit=limit)
558+
559+
def get_indexer_non_unique(self, targets):
560+
ordinal = periodlib.extract_ordinals(targets, self.vgetter().freq)
561+
ordinal_array = np.asarray(ordinal)
562+
563+
return super(PeriodEngine, self).get_indexer_non_unique(ordinal_array)
564+
565+
493566
cpdef convert_scalar(ndarray arr, object value):
494567
# we don't turn integers
495568
# into datetimes/timedeltas

0 commit comments

Comments
 (0)