@@ -5,7 +5,7 @@ from cython cimport Py_ssize_t
5
5
6
6
import numpy as np
7
7
cimport numpy as cnp
8
- from numpy cimport ndarray, int64_t
8
+ from numpy cimport ndarray, int64_t, int32_t
9
9
cnp.import_array()
10
10
11
11
from util cimport is_string_object, get_nat
@@ -45,12 +45,12 @@ cdef int RESO_MIN = 4
45
45
cdef int RESO_HR = 5
46
46
cdef int RESO_DAY = 6
47
47
48
- _ONE_MICRO = 1000L
49
- _ONE_MILLI = _ONE_MICRO * 1000
50
- _ONE_SECOND = _ONE_MILLI * 1000
51
- _ONE_MINUTE = 60 * _ONE_SECOND
52
- _ONE_HOUR = 60 * _ONE_MINUTE
53
- _ONE_DAY = 24 * _ONE_HOUR
48
+ _ONE_MICRO = < int64_t > 1000L
49
+ _ONE_MILLI = < int64_t > ( _ONE_MICRO * 1000 )
50
+ _ONE_SECOND = < int64_t > ( _ONE_MILLI * 1000 )
51
+ _ONE_MINUTE = < int64_t > ( 60 * _ONE_SECOND)
52
+ _ONE_HOUR = < int64_t > ( 60 * _ONE_MINUTE)
53
+ _ONE_DAY = < int64_t > ( 24 * _ONE_HOUR)
54
54
55
55
# ----------------------------------------------------------------------
56
56
@@ -350,7 +350,7 @@ class Resolution(object):
350
350
# TODO: this is non performant logic here (and duplicative) and this
351
351
# simply should call unique_1d directly
352
352
# plus no reason to depend on khash directly
353
- cdef unique_deltas(ndarray[int64_t] arr):
353
+ cdef ndarray[int64_t, ndim = 1 ] unique_deltas(ndarray[int64_t] arr):
354
354
cdef:
355
355
Py_ssize_t i, n = len (arr)
356
356
int64_t val
@@ -374,21 +374,27 @@ cdef unique_deltas(ndarray[int64_t] arr):
374
374
return result
375
375
376
376
377
- def _is_multiple (us , mult ):
377
+ cdef inline bint _is_multiple(int64_t us, int64_t mult):
378
378
return us % mult == 0
379
379
380
380
381
- def _maybe_add_count (base , count ):
381
+ cdef inline str _maybe_add_count(str base, int64_t count):
382
382
if count != 1 :
383
- return ' {count}{base}' .format(count = int ( count) , base = base)
383
+ return ' {count}{base}' .format(count = count, base = base)
384
384
else :
385
385
return base
386
386
387
387
388
- class _FrequencyInferer (object ):
388
+ cdef class _FrequencyInferer(object ):
389
389
"""
390
390
Not sure if I can avoid the state machine here
391
391
"""
392
+ cdef public:
393
+ object index
394
+ object values
395
+ bint warn
396
+ bint is_monotonic
397
+ dict _cache
392
398
393
399
def __init__ (self , index , warn = True ):
394
400
self .index = index
@@ -476,16 +482,23 @@ class _FrequencyInferer(object):
476
482
def rep_stamp (self ):
477
483
return Timestamp(self .values[0 ])
478
484
479
- def month_position_check (self ):
485
+ cdef month_position_check(self ):
480
486
# TODO: cythonize this, very slow
481
- calendar_end = True
482
- business_end = True
483
- calendar_start = True
484
- business_start = True
485
-
486
- years = self .fields[' Y' ]
487
- months = self .fields[' M' ]
488
- days = self .fields[' D' ]
487
+ cdef:
488
+ int32_t daysinmonth, y, m, d
489
+ bint calendar_end = True
490
+ bint business_end = True
491
+ bint calendar_start = True
492
+ bint business_start = True
493
+ bint cal
494
+ int32_t[:] years
495
+ int32_t[:] months
496
+ int32_t[:] days
497
+
498
+ fields = self .fields
499
+ years = fields[' Y' ]
500
+ months = fields[' M' ]
501
+ days = fields[' D' ]
489
502
weekdays = self .index.dayofweek
490
503
491
504
for y, m, d, wd in zip (years, months, days, weekdays):
@@ -525,7 +538,7 @@ class _FrequencyInferer(object):
525
538
def ydiffs (self ):
526
539
return unique_deltas(self .fields[' Y' ].astype(' i8' ))
527
540
528
- def _infer_daily_rule (self ):
541
+ cdef _infer_daily_rule(self ):
529
542
annual_rule = self ._get_annual_rule()
530
543
if annual_rule:
531
544
nyears = self .ydiffs[0 ]
@@ -562,7 +575,7 @@ class _FrequencyInferer(object):
562
575
if wom_rule:
563
576
return wom_rule
564
577
565
- def _get_annual_rule (self ):
578
+ cdef _get_annual_rule(self ):
566
579
if len (self .ydiffs) > 1 :
567
580
return None
568
581
@@ -573,7 +586,7 @@ class _FrequencyInferer(object):
573
586
return {' cs' : ' AS' , ' bs' : ' BAS' ,
574
587
' ce' : ' A' , ' be' : ' BA' }.get(pos_check)
575
588
576
- def _get_quarterly_rule (self ):
589
+ cdef _get_quarterly_rule(self ):
577
590
if len (self .mdiffs) > 1 :
578
591
return None
579
592
@@ -584,14 +597,14 @@ class _FrequencyInferer(object):
584
597
return {' cs' : ' QS' , ' bs' : ' BQS' ,
585
598
' ce' : ' Q' , ' be' : ' BQ' }.get(pos_check)
586
599
587
- def _get_monthly_rule (self ):
600
+ cdef _get_monthly_rule(self ):
588
601
if len (self .mdiffs) > 1 :
589
602
return None
590
603
pos_check = self .month_position_check()
591
604
return {' cs' : ' MS' , ' bs' : ' BMS' ,
592
605
' ce' : ' M' , ' be' : ' BM' }.get(pos_check)
593
606
594
- def _is_business_daily (self ):
607
+ cdef bint _is_business_daily(self ):
595
608
# quick check: cannot be business daily
596
609
if self .day_deltas != [1 , 3 ]:
597
610
return False
@@ -604,7 +617,7 @@ class _FrequencyInferer(object):
604
617
return np.all(((weekdays == 0 ) & (shifts == 3 )) |
605
618
((weekdays > 0 ) & (weekdays <= 4 ) & (shifts == 1 )))
606
619
607
- def _get_wom_rule (self ):
620
+ cdef _get_wom_rule(self ):
608
621
# wdiffs = unique(np.diff(self.index.week))
609
622
# We also need -47, -49, -48 to catch index spanning year boundary
610
623
# if not lib.ismember(wdiffs, set([4, 5, -47, -49, -48])).all():
@@ -627,9 +640,9 @@ class _FrequencyInferer(object):
627
640
return ' WOM-{week}{weekday}' .format(week = week, weekday = wd)
628
641
629
642
630
- class _TimedeltaFrequencyInferer (_FrequencyInferer ):
643
+ cdef class _TimedeltaFrequencyInferer(_FrequencyInferer):
631
644
632
- def _infer_daily_rule (self ):
645
+ cdef _infer_daily_rule(self ):
633
646
if self .is_unique:
634
647
days = self .deltas[0 ] / _ONE_DAY
635
648
if days % 7 == 0 :
0 commit comments