@@ -66,7 +66,7 @@ def isnull(obj):
66
66
result = Series (result , index = obj .index , copy = False )
67
67
elif obj .dtype == np .datetime64 :
68
68
# this is the NaT pattern
69
- result = obj .ravel (). view ('i8' ) == 0x8000000000000000
69
+ result = obj .view ('i8' ) == lib . NaT
70
70
else :
71
71
result = - np .isfinite (obj )
72
72
return result
@@ -106,43 +106,59 @@ def _unpickle_array(bytes):
106
106
arr = read_array (BytesIO (bytes ))
107
107
return arr
108
108
109
- def _take_1d_bool (arr , indexer , out , fill_value = np .nan ):
110
- view = arr .view (np .uint8 )
111
- outview = out .view (np .uint8 )
109
+ def _take_1d_datetime (arr , indexer , out , fill_value = np .nan ):
110
+ view = arr .view (np .int64 )
111
+ outview = out .view (np .int64 )
112
112
lib .take_1d_bool (view , indexer , outview , fill_value = fill_value )
113
113
114
- def _take_2d_axis0_bool (arr , indexer , out , fill_value = np .nan ):
115
- view = arr .view (np .uint8 )
116
- outview = out .view (np .uint8 )
117
- lib .take_2d_axis0_bool (view , indexer , outview , fill_value = fill_value )
114
+ def _take_2d_axis0_datetime (arr , indexer , out , fill_value = np .nan ):
115
+ view = arr .view (np .int64 )
116
+ outview = out .view (np .int64 )
117
+ lib .take_1d_bool (view , indexer , outview , fill_value = fill_value )
118
118
119
- def _take_2d_axis1_bool (arr , indexer , out , fill_value = np .nan ):
119
+ def _take_2d_axis1_datetime (arr , indexer , out , fill_value = np .nan ):
120
120
view = arr .view (np .uint8 )
121
121
outview = out .view (np .uint8 )
122
- lib .take_2d_axis1_bool (view , indexer , outview , fill_value = fill_value )
122
+ lib .take_1d_bool (view , indexer , outview , fill_value = fill_value )
123
+
124
+ def _view_wrapper (f , wrap_dtype , na_override = None ):
125
+ def wrapper (arr , indexer , out , fill_value = np .nan ):
126
+ if na_override is not None and np .isnan (fill_value ):
127
+ fill_value = na_override
128
+ view = arr .view (wrap_dtype )
129
+ outview = out .view (wrap_dtype )
130
+ f (view , indexer , outview , fill_value = fill_value )
131
+ return wrapper
132
+
123
133
124
134
_take1d_dict = {
125
135
'float64' : lib .take_1d_float64 ,
126
136
'int32' : lib .take_1d_int32 ,
127
137
'int64' : lib .take_1d_int64 ,
128
138
'object' : lib .take_1d_object ,
129
- 'bool' : _take_1d_bool
139
+ 'bool' : _view_wrapper (lib .take_1d_bool , np .uint8 ),
140
+ 'datetime64[us]' : _view_wrapper (lib .take_1d_int64 , np .int64 ,
141
+ na_override = lib .NaT ),
130
142
}
131
143
132
144
_take2d_axis0_dict = {
133
145
'float64' : lib .take_2d_axis0_float64 ,
134
146
'int32' : lib .take_2d_axis0_int32 ,
135
147
'int64' : lib .take_2d_axis0_int64 ,
136
148
'object' : lib .take_2d_axis0_object ,
137
- 'bool' : _take_2d_axis0_bool
149
+ 'bool' : _view_wrapper (lib .take_2d_axis0_bool , np .uint8 ),
150
+ 'datetime64[us]' : _view_wrapper (lib .take_2d_axis0_int64 , np .int64 ,
151
+ na_override = lib .NaT ),
138
152
}
139
153
140
154
_take2d_axis1_dict = {
141
155
'float64' : lib .take_2d_axis1_float64 ,
142
156
'int32' : lib .take_2d_axis1_int32 ,
143
157
'int64' : lib .take_2d_axis1_int64 ,
144
158
'object' : lib .take_2d_axis1_object ,
145
- 'bool' : _take_2d_axis1_bool
159
+ 'bool' : _view_wrapper (lib .take_2d_axis1_bool , np .uint8 ),
160
+ 'datetime64[us]' : _view_wrapper (lib .take_2d_axis1_int64 , np .int64 ,
161
+ na_override = lib .NaT ),
146
162
}
147
163
148
164
def _get_take2d_function (dtype_str , axis = 0 ):
@@ -164,14 +180,13 @@ def take_1d(arr, indexer, out=None, fill_value=np.nan):
164
180
indexer = np .array (indexer , dtype = np .int32 )
165
181
166
182
indexer = _ensure_int32 (indexer )
167
-
168
183
out_passed = out is not None
184
+ take_f = _take1d_dict .get (dtype_str )
169
185
170
186
if dtype_str in ('int32' , 'int64' , 'bool' ):
171
187
try :
172
188
if out is None :
173
189
out = np .empty (n , dtype = arr .dtype )
174
- take_f = _take1d_dict [dtype_str ]
175
190
take_f (arr , indexer , out = out , fill_value = fill_value )
176
191
except ValueError :
177
192
mask = indexer == - 1
@@ -186,10 +201,9 @@ def take_1d(arr, indexer, out=None, fill_value=np.nan):
186
201
out .dtype )
187
202
out = _maybe_upcast (out )
188
203
np .putmask (out , mask , fill_value )
189
- elif dtype_str in ('float64' , 'object' ):
204
+ elif dtype_str in ('float64' , 'object' , 'datetime64[us]' ):
190
205
if out is None :
191
206
out = np .empty (n , dtype = arr .dtype )
192
- take_f = _take1d_dict [dtype_str ]
193
207
take_f (arr , indexer , out = out , fill_value = fill_value )
194
208
else :
195
209
out = arr .take (indexer , out = out )
@@ -238,7 +252,7 @@ def take_2d(arr, indexer, out=None, mask=None, needs_masking=None, axis=0,
238
252
take_f = _get_take2d_function (dtype_str , axis = axis )
239
253
take_f (arr , indexer , out = out , fill_value = fill_value )
240
254
return out
241
- elif dtype_str in ('float64' , 'object' ):
255
+ elif dtype_str in ('float64' , 'object' , 'datetime64[us]' ):
242
256
if out is None :
243
257
out = np .empty (out_shape , dtype = arr .dtype )
244
258
take_f = _get_take2d_function (dtype_str , axis = axis )
@@ -301,9 +315,22 @@ def _need_upcast(values):
301
315
return True
302
316
return False
303
317
318
+ def _interp_wrapper (f , wrap_dtype , na_override = None ):
319
+ def wrapper (arr , mask , limit = None ):
320
+ view = arr .view (wrap_dtype )
321
+ f (view , mask , limit = limit )
322
+ return wrapper
323
+
324
+ _pad_1d_datetime = _interp_wrapper (lib .pad_inplace_int64 , np .int64 )
325
+ _pad_2d_datetime = _interp_wrapper (lib .pad_2d_inplace_int64 , np .int64 )
326
+ _backfill_1d_datetime = _interp_wrapper (lib .backfill_inplace_int64 , np .int64 )
327
+ _backfill_2d_datetime = _interp_wrapper (lib .backfill_2d_inplace_int64 , np .int64 )
328
+
304
329
def pad_1d (values , limit = None ):
305
330
if is_float_dtype (values ):
306
331
_method = lib .pad_inplace_float64
332
+ elif is_datetime64_dtype (values ):
333
+ _method = _pad_1d_datetime
307
334
elif values .dtype == np .object_ :
308
335
_method = lib .pad_inplace_object
309
336
else : # pragma: no cover
@@ -314,21 +341,48 @@ def pad_1d(values, limit=None):
314
341
def backfill_1d (values , limit = None ):
315
342
if is_float_dtype (values ):
316
343
_method = lib .backfill_inplace_float64
344
+ elif is_datetime64_dtype (values ):
345
+ _method = _backfill_1d_datetime
317
346
elif values .dtype == np .object_ :
318
347
_method = lib .backfill_inplace_object
319
348
else : # pragma: no cover
320
349
raise ValueError ('Invalid dtype for padding' )
321
350
322
351
_method (values , isnull (values ).view (np .uint8 ), limit = limit )
323
352
353
+ def pad_2d (values , limit = None ):
354
+ if is_float_dtype (values ):
355
+ _method = lib .pad_2d_inplace_float64
356
+ elif is_datetime64_dtype (values ):
357
+ _method = _pad_2d_datetime
358
+ elif values .dtype == np .object_ :
359
+ _method = lib .pad_2d_inplace_object
360
+ else : # pragma: no cover
361
+ raise ValueError ('Invalid dtype for padding' )
362
+
363
+ _method (values , isnull (values ).view (np .uint8 ), limit = limit )
364
+
365
+ def backfill_2d (values , limit = None ):
366
+ if is_float_dtype (values ):
367
+ _method = lib .backfill_2d_inplace_float64
368
+ elif is_datetime64_dtype (values ):
369
+ _method = _backfill_2d_datetime
370
+ elif values .dtype == np .object_ :
371
+ _method = lib .backfill_2d_inplace_object
372
+ else : # pragma: no cover
373
+ raise ValueError ('Invalid dtype for padding' )
374
+
375
+ _method (values , isnull (values ).view (np .uint8 ), limit = limit )
376
+
377
+
324
378
def _consensus_name_attr (objs ):
325
379
name = objs [0 ].name
326
380
for obj in objs [1 :]:
327
381
if obj .name != name :
328
382
return None
329
383
return name
330
384
331
- #-------------------------------------------------------------------------------
385
+ #----------------------------------------------------------------------
332
386
# Lots of little utilities
333
387
334
388
def _infer_dtype (value ):
@@ -579,6 +633,13 @@ def is_integer_dtype(arr_or_dtype):
579
633
return (issubclass (tipo , np .integer ) and not
580
634
issubclass (tipo , np .datetime64 ))
581
635
636
+ def is_datetime64_dtype (arr_or_dtype ):
637
+ if isinstance (arr_or_dtype , np .dtype ):
638
+ tipo = arr_or_dtype .type
639
+ else :
640
+ tipo = arr_or_dtype .dtype .type
641
+ return issubclass (tipo , np .datetime64 )
642
+
582
643
def is_float_dtype (arr_or_dtype ):
583
644
if isinstance (arr_or_dtype , np .dtype ):
584
645
tipo = arr_or_dtype .type
0 commit comments