3
3
from datetime import time , datetime , date
4
4
from datetime import timedelta
5
5
from itertools import izip
6
+ import weakref
6
7
7
8
import numpy as np
8
9
@@ -57,21 +58,26 @@ class Index(np.ndarray):
57
58
----
58
59
An Index instance can **only** contain hashable objects
59
60
"""
61
+ # _algos = {
62
+ # 'groupby' : _gin.groupby_index,
63
+ # }
64
+
65
+ # _map_indices = lib.map_indices_object
66
+
60
67
# Cython methods
61
- _map_indices = lib .map_indices_object
62
- _is_monotonic = lib .is_monotonic_object
63
68
_groupby = lib .groupby_object
64
69
_arrmap = lib .arrmap_object
65
70
_left_indexer = lib .left_join_indexer_object
66
71
_inner_indexer = lib .inner_join_indexer_object
67
72
_outer_indexer = lib .outer_join_indexer_object
68
- _merge_indexer = lib .merge_indexer_object
69
73
_pad = lib .pad_object
70
74
_backfill = lib .backfill_object
71
75
72
76
name = None
73
77
asi8 = None
74
78
79
+ _engine_type = _gin .ObjectEngine
80
+
75
81
def __new__ (cls , data , dtype = None , copy = False , name = None ):
76
82
if isinstance (data , np .ndarray ):
77
83
if dtype is None :
@@ -164,25 +170,11 @@ def values(self):
164
170
165
171
@property
166
172
def is_monotonic (self ):
167
- return self ._monotonicity_check [0 ]
168
-
169
- @property
170
- def is_unique (self ):
171
- is_unique = self ._monotonicity_check [1 ]
172
-
173
- if is_unique is None :
174
- return self ._engine .has_integrity
175
- else :
176
- return is_unique
173
+ return self ._engine .is_monotonic
177
174
178
175
@cache_readonly
179
- def _monotonicity_check (self ):
180
- try :
181
- # wrong buffer type raises ValueError
182
- is_monotonic , is_unique = self ._is_monotonic (self .values )
183
- return is_monotonic , is_unique
184
- except TypeError :
185
- return False , None
176
+ def is_unique (self ):
177
+ return self ._engine .is_unique
186
178
187
179
def is_numeric (self ):
188
180
return self .inferred_type in ['integer' , 'floating' ]
@@ -210,20 +202,13 @@ def get_duplicates(self):
210
202
211
203
_get_duplicates = get_duplicates
212
204
213
- @property
214
- def indexMap (self ):
215
- "{label -> location}"
216
- return self ._engine .get_mapping (1 )
217
-
218
205
def _cleanup (self ):
219
206
self ._engine .clear_mapping ()
220
207
221
208
@cache_readonly
222
209
def _engine (self ):
223
- import weakref
224
210
# property, for now, slow to look up
225
- return _gin .DictIndexEngine (weakref .ref (self ),
226
- self ._map_indices )
211
+ return self ._engine_type (weakref .ref (self ))
227
212
228
213
def _get_level_number (self , level ):
229
214
if not isinstance (level , int ):
@@ -574,7 +559,15 @@ def get_loc(self, key):
574
559
-------
575
560
loc : int
576
561
"""
577
- return self ._engine .get_loc (key )
562
+ # TODO: push all of this into Cython
563
+ if self .is_unique :
564
+ return self ._engine .get_loc (key )
565
+ elif self .is_monotonic :
566
+ left = self .searchsorted (key , side = 'left' )
567
+ right = self .searchsorted (key , side = 'right' )
568
+ return slice (left , right )
569
+ else :
570
+ return self .values == key
578
571
579
572
def get_value (self , series , key ):
580
573
"""
@@ -664,7 +657,7 @@ def _get_indexer_standard(self, other):
664
657
self .is_monotonic and other .is_monotonic ):
665
658
return self ._left_indexer (other , self )
666
659
else :
667
- return self ._merge_indexer (other , self . indexMap )
660
+ return self ._engine . get_indexer (other )
668
661
669
662
def groupby (self , to_groupby ):
670
663
return self ._groupby (self .values , to_groupby )
@@ -995,16 +988,19 @@ def copy(self, order='C'):
995
988
class Int64Index (Index ):
996
989
997
990
_map_indices = lib .map_indices_int64
998
- _is_monotonic = lib .is_monotonic_int64
991
+
992
+ # _is_monotonic = lib.is_monotonic_int64
993
+
999
994
_groupby = lib .groupby_int64
1000
995
_arrmap = lib .arrmap_int64
1001
996
_left_indexer = lib .left_join_indexer_int64
1002
997
_inner_indexer = lib .inner_join_indexer_int64
1003
998
_outer_indexer = lib .outer_join_indexer_int64
1004
- _merge_indexer = lib .merge_indexer_int64
1005
999
_pad = lib .pad_int64
1006
1000
_backfill = lib .backfill_int64
1007
1001
1002
+ _engine_type = _gin .Int64Engine
1003
+
1008
1004
def __new__ (cls , data , dtype = None , copy = False , name = None ):
1009
1005
if not isinstance (data , np .ndarray ):
1010
1006
if np .isscalar (data ):
@@ -1172,13 +1168,12 @@ class DatetimeIndex(Int64Index):
1172
1168
time on or just past end argument
1173
1169
"""
1174
1170
1175
- _is_monotonic = _wrap_i8_function (lib .is_monotonic_int64 )
1171
+ # _is_monotonic = _wrap_i8_function(lib.is_monotonic_int64)
1172
+
1176
1173
_inner_indexer = _join_i8_wrapper (lib .inner_join_indexer_int64 )
1177
1174
_outer_indexer = _join_i8_wrapper (lib .outer_join_indexer_int64 )
1178
1175
_left_indexer = _join_i8_wrapper (lib .left_join_indexer_int64 ,
1179
1176
with_indexers = False )
1180
- _merge_indexer = _join_i8_wrapper (lib .merge_indexer_int64 ,
1181
- with_indexers = False )
1182
1177
_map_indices = _wrap_i8_function (lib .map_indices_int64 )
1183
1178
_pad = _wrap_i8_function (lib .pad_int64 )
1184
1179
_backfill = _wrap_i8_function (lib .backfill_int64 )
@@ -1199,6 +1194,10 @@ class DatetimeIndex(Int64Index):
1199
1194
# structured array cache for datetime fields
1200
1195
_sarr_cache = None
1201
1196
1197
+ _engine_type = _gin .DatetimeEngine
1198
+
1199
+ offset = None
1200
+
1202
1201
def __new__ (cls , data = None ,
1203
1202
freq = None , start = None , end = None , periods = None ,
1204
1203
dtype = None , copy = False , name = None , tz = None ,
@@ -1437,7 +1436,6 @@ def asobject(self):
1437
1436
"""
1438
1437
Unbox to an index of type object
1439
1438
"""
1440
- offset = getattr (self , 'offset' , None )
1441
1439
boxed_values = _dt_box_array (self .asi8 , self .offset , self .tz )
1442
1440
return Index (boxed_values , dtype = object )
1443
1441
@@ -1656,7 +1654,7 @@ def get_value(self, series, key):
1656
1654
know what you're doing
1657
1655
"""
1658
1656
try :
1659
- return super ( DatetimeIndex , self ) .get_value (series , key )
1657
+ return Index .get_value (self , series , key )
1660
1658
except KeyError :
1661
1659
try :
1662
1660
asdt , parsed , reso = datetools .parse_time_string (key )
@@ -1698,8 +1696,7 @@ def __getitem__(self, key):
1698
1696
arr_idx = self .view (np .ndarray )
1699
1697
if np .isscalar (key ):
1700
1698
val = arr_idx [key ]
1701
- offset = getattr (self , 'offset' , None )
1702
- return _dt_box (val , offset = offset , tz = self .tz )
1699
+ return _dt_box (val , offset = self .offset , tz = self .tz )
1703
1700
else :
1704
1701
new_offset = None
1705
1702
if (type (key ) == slice ):
@@ -1814,11 +1811,6 @@ def dtype(self):
1814
1811
def is_all_dates (self ):
1815
1812
return True
1816
1813
1817
- @cache_readonly
1818
- def _engine (self ):
1819
- mapping = lib .map_indices_int64
1820
- return _gin .DictIndexEngineDatetime (self .asi8 , mapping )
1821
-
1822
1814
def equals (self , other ):
1823
1815
"""
1824
1816
Determines if two Index objects contain the same elements.
@@ -2977,7 +2969,7 @@ def get_indexer(self, target, method=None):
2977
2969
indexer = self ._backfill (self_index , target_index ,
2978
2970
self_index .indexMap , target .indexMap )
2979
2971
else :
2980
- indexer = self ._merge_indexer (target_index , self_index . indexMap )
2972
+ indexer = self ._engine . get_indexer (target_index )
2981
2973
2982
2974
return indexer
2983
2975
0 commit comments