@@ -17,7 +17,7 @@ from tslib cimport _to_i8
17
17
18
18
from hashtable cimport HashTable
19
19
20
- from pandas._libs import algos, hashtable as _hash
20
+ from pandas._libs import algos, period as periodlib, hashtable as _hash
21
21
from pandas._libs.tslib import Timestamp, Timedelta
22
22
from datetime import datetime, timedelta
23
23
@@ -270,13 +270,16 @@ cdef class IndexEngine:
270
270
271
271
values = self ._get_index_values()
272
272
self .mapping = self ._make_hash_table(len (values))
273
- self .mapping.map_locations (values)
273
+ self ._call_map_locations (values)
274
274
275
275
if len (self .mapping) == len (values):
276
276
self .unique = 1
277
277
278
278
self .need_unique_check = 0
279
279
280
+ cpdef _call_map_locations(self , values):
281
+ self .mapping.map_locations(values)
282
+
280
283
def clear_mapping (self ):
281
284
self .mapping = None
282
285
self .need_monotonic_check = 1
@@ -491,6 +494,76 @@ cdef class TimedeltaEngine(DatetimeEngine):
491
494
cdef _get_box_dtype(self ):
492
495
return ' m8[ns]'
493
496
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
+
494
567
cpdef convert_scalar(ndarray arr, object value):
495
568
# we don't turn integers
496
569
# into datetimes/timedeltas
0 commit comments