@@ -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
@@ -490,6 +493,76 @@ cdef class TimedeltaEngine(DatetimeEngine):
490
493
cdef _get_box_dtype(self ):
491
494
return ' m8[ns]'
492
495
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
+
493
566
cpdef convert_scalar(ndarray arr, object value):
494
567
# we don't turn integers
495
568
# into datetimes/timedeltas
0 commit comments