@@ -75,7 +75,7 @@ def f(values, axis=None, skipna=True, **kwds):
75
75
result .fill (0 )
76
76
return result
77
77
78
- if _USE_BOTTLENECK and skipna and _bn_ok_dtype (values .dtype ):
78
+ if _USE_BOTTLENECK and skipna and _bn_ok_dtype (values .dtype , bn_name ):
79
79
result = bn_func (values , axis = axis , ** kwds )
80
80
81
81
# prefer to treat inf/-inf as NA, but must compute the func
@@ -92,11 +92,18 @@ def f(values, axis=None, skipna=True, **kwds):
92
92
return f
93
93
94
94
95
- def _bn_ok_dtype (dt ):
95
+ def _bn_ok_dtype (dt , name ):
96
96
# Bottleneck chokes on datetime64
97
- time_types = np .datetime64 , np .timedelta64
98
- return dt != np .object_ and not issubclass (dt .type , time_types )
97
+ if dt != np .object_ and not issubclass (dt .type , (np .datetime64 , np .timedelta64 )):
99
98
99
+ # bottleneck does not properly upcast during the sum
100
+ # so can overflow
101
+ if name == 'nansum' :
102
+ if dt != np .bool_ and dt .itemsize < 8 :
103
+ return False
104
+
105
+ return True
106
+ return False
100
107
101
108
def _has_infs (result ):
102
109
if isinstance (result , np .ndarray ):
@@ -165,7 +172,18 @@ def _get_values(values, skipna, fill_value=None, fill_value_typ=None,
165
172
values = values .copy ()
166
173
167
174
values = _view_if_needed (values )
168
- return values , mask , dtype
175
+
176
+ # return a platform independent precision dtype
177
+ dtype_max = dtype
178
+ if dtype .kind == 'i' and not issubclass (
179
+ dtype .type , (np .bool , np .datetime64 , np .timedelta64 )):
180
+ dtype_max = np .int64
181
+ elif dtype .kind in ['b' ] or issubclass (dtype .type , np .bool ):
182
+ dtype_max = np .int64
183
+ elif dtype .kind in ['f' ]:
184
+ dtype_max = np .float64
185
+
186
+ return values , mask , dtype , dtype_max
169
187
170
188
171
189
def _isfinite (values ):
@@ -216,20 +234,20 @@ def _wrap_results(result, dtype):
216
234
217
235
218
236
def nanany (values , axis = None , skipna = True ):
219
- values , mask , dtype = _get_values (values , skipna , False , copy = skipna )
237
+ values , mask , dtype , _ = _get_values (values , skipna , False , copy = skipna )
220
238
return values .any (axis )
221
239
222
240
223
241
def nanall (values , axis = None , skipna = True ):
224
- values , mask , dtype = _get_values (values , skipna , True , copy = skipna )
242
+ values , mask , dtype , _ = _get_values (values , skipna , True , copy = skipna )
225
243
return values .all (axis )
226
244
227
245
228
246
@disallow ('M8' )
229
247
@bottleneck_switch (zero_value = 0 )
230
248
def nansum (values , axis = None , skipna = True ):
231
- values , mask , dtype = _get_values (values , skipna , 0 )
232
- the_sum = values .sum (axis )
249
+ values , mask , dtype , dtype_max = _get_values (values , skipna , 0 )
250
+ the_sum = values .sum (axis , dtype = dtype_max )
233
251
the_sum = _maybe_null_out (the_sum , axis , mask )
234
252
235
253
return _wrap_results (the_sum , dtype )
@@ -238,8 +256,8 @@ def nansum(values, axis=None, skipna=True):
238
256
@disallow ('M8' )
239
257
@bottleneck_switch ()
240
258
def nanmean (values , axis = None , skipna = True ):
241
- values , mask , dtype = _get_values (values , skipna , 0 )
242
- the_sum = _ensure_numeric (values .sum (axis ))
259
+ values , mask , dtype , dtype_max = _get_values (values , skipna , 0 )
260
+ the_sum = _ensure_numeric (values .sum (axis , dtype = dtype_max ))
243
261
count = _get_counts (mask , axis )
244
262
245
263
if axis is not None :
@@ -257,7 +275,7 @@ def nanmean(values, axis=None, skipna=True):
257
275
@bottleneck_switch ()
258
276
def nanmedian (values , axis = None , skipna = True ):
259
277
260
- values , mask , dtype = _get_values (values , skipna )
278
+ values , mask , dtype , dtype_max = _get_values (values , skipna )
261
279
262
280
def get_median (x ):
263
281
mask = notnull (x )
@@ -325,7 +343,7 @@ def nanvar(values, axis=None, skipna=True, ddof=1):
325
343
326
344
@bottleneck_switch ()
327
345
def nanmin (values , axis = None , skipna = True ):
328
- values , mask , dtype = _get_values (values , skipna , fill_value_typ = '+inf' )
346
+ values , mask , dtype , dtype_max = _get_values (values , skipna , fill_value_typ = '+inf' )
329
347
330
348
# numpy 1.6.1 workaround in Python 3.x
331
349
if (values .dtype == np .object_ and compat .PY3 ):
@@ -341,7 +359,7 @@ def nanmin(values, axis=None, skipna=True):
341
359
if ((axis is not None and values .shape [axis ] == 0 )
342
360
or values .size == 0 ):
343
361
try :
344
- result = com .ensure_float (values .sum (axis ))
362
+ result = com .ensure_float (values .sum (axis , dtype = dtype_max ))
345
363
result .fill (np .nan )
346
364
except :
347
365
result = np .nan
@@ -354,7 +372,7 @@ def nanmin(values, axis=None, skipna=True):
354
372
355
373
@bottleneck_switch ()
356
374
def nanmax (values , axis = None , skipna = True ):
357
- values , mask , dtype = _get_values (values , skipna , fill_value_typ = '-inf' )
375
+ values , mask , dtype , dtype_max = _get_values (values , skipna , fill_value_typ = '-inf' )
358
376
359
377
# numpy 1.6.1 workaround in Python 3.x
360
378
if (values .dtype == np .object_ and compat .PY3 ):
@@ -371,7 +389,7 @@ def nanmax(values, axis=None, skipna=True):
371
389
if ((axis is not None and values .shape [axis ] == 0 )
372
390
or values .size == 0 ):
373
391
try :
374
- result = com .ensure_float (values .sum (axis ))
392
+ result = com .ensure_float (values .sum (axis , dtype = dtype_max ))
375
393
result .fill (np .nan )
376
394
except :
377
395
result = np .nan
@@ -386,7 +404,7 @@ def nanargmax(values, axis=None, skipna=True):
386
404
"""
387
405
Returns -1 in the NA case
388
406
"""
389
- values , mask , dtype = _get_values (values , skipna , fill_value_typ = '-inf' ,
407
+ values , mask , dtype , _ = _get_values (values , skipna , fill_value_typ = '-inf' ,
390
408
isfinite = True )
391
409
result = values .argmax (axis )
392
410
result = _maybe_arg_null_out (result , axis , mask , skipna )
@@ -397,7 +415,7 @@ def nanargmin(values, axis=None, skipna=True):
397
415
"""
398
416
Returns -1 in the NA case
399
417
"""
400
- values , mask , dtype = _get_values (values , skipna , fill_value_typ = '+inf' ,
418
+ values , mask , dtype , _ = _get_values (values , skipna , fill_value_typ = '+inf' ,
401
419
isfinite = True )
402
420
result = values .argmin (axis )
403
421
result = _maybe_arg_null_out (result , axis , mask , skipna )
0 commit comments