Skip to content

Commit 06f087c

Browse files
committed
BUG: Create PeriodEngine
1 parent 4489389 commit 06f087c

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

pandas/_libs/index.pyx

+75-2
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
@@ -491,6 +494,76 @@ cdef class TimedeltaEngine(DatetimeEngine):
491494
cdef _get_box_dtype(self):
492495
return 'm8[ns]'
493496

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

0 commit comments

Comments
 (0)