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