@@ -200,14 +200,34 @@ def _get_fill_value(dtype, fill_value=None, fill_value_typ=None):
200
200
return tslibs .iNaT
201
201
202
202
203
- def _get_values (values , skipna , fill_value = None , fill_value_typ = None ,
204
- isfinite = False , copy = True , mask = None , compute_mask = True ):
203
+ def _maybe_get_mask (values , skipna , mask ):
204
+ """ This function will return a mask iff it is necessary. Otherwise, return
205
+ None when a mask is not needed.
206
+ """
207
+ if (hasattr (values , 'dtype' ) and is_bool_dtype (values .dtype )):
208
+ # Boolean data cannot contain nulls, so signal via mask being None
209
+ return None
210
+
211
+ mask = _get_mask (values , mask , skipna = skipna )
212
+
213
+ return mask
214
+
215
+
216
+ def _get_mask (values , mask , skipna = True ):
217
+ if mask is None and skipna :
218
+ mask = isna (values )
219
+ return mask
220
+
221
+
222
+ def _get_values (values , skipna , mask , fill_value = None , fill_value_typ = None ,
223
+ copy = True ):
205
224
""" utility to get the values view, mask, dtype
206
225
if necessary copy and mask using the specified fill_value
207
226
copy = True will force the copy
208
227
"""
209
- if skipna :
210
- compute_mask = True
228
+ if mask is None :
229
+ # We're relying on _maybe_get_mask to determine if a mask is necessary
230
+ skipna = False
211
231
212
232
if is_datetime64tz_dtype (values ):
213
233
# com.values_from_object returns M8[ns] dtype instead of tz-aware,
@@ -218,12 +238,6 @@ def _get_values(values, skipna, fill_value=None, fill_value_typ=None,
218
238
values = com .values_from_object (values )
219
239
dtype = values .dtype
220
240
221
- if mask is None and compute_mask :
222
- if isfinite :
223
- mask = _isfinite (values )
224
- else :
225
- mask = isna (values )
226
-
227
241
if is_datetime_or_timedelta_dtype (values ) or is_datetime64tz_dtype (values ):
228
242
# changing timedelta64/datetime64 to int64 needs to happen after
229
243
# finding `mask` above
@@ -257,7 +271,7 @@ def _get_values(values, skipna, fill_value=None, fill_value_typ=None,
257
271
elif is_float_dtype (dtype ):
258
272
dtype_max = np .float64
259
273
260
- return values , mask , dtype , dtype_max , fill_value
274
+ return values , dtype , dtype_max , fill_value
261
275
262
276
263
277
def _isfinite (values ):
@@ -364,12 +378,9 @@ def nanany(values, axis=None, skipna=True, mask=None):
364
378
>>> nanops.nanany(s)
365
379
False
366
380
"""
367
- if (hasattr (values , 'dtype' ) and is_bool_dtype (values .dtype ) and
368
- mask is None ):
369
- # Assume np.bool cannot store NaNs
370
- skipna = False
371
- values , _ , _ , _ , _ = _get_values (values , skipna , False , copy = skipna ,
372
- mask = mask , compute_mask = False )
381
+ mask = _maybe_get_mask (values , skipna , mask )
382
+ values , _ , _ , _ = _get_values (values , skipna , mask , fill_value = False ,
383
+ copy = skipna )
373
384
return values .any (axis )
374
385
375
386
@@ -401,12 +412,9 @@ def nanall(values, axis=None, skipna=True, mask=None):
401
412
>>> nanops.nanall(s)
402
413
False
403
414
"""
404
- if (hasattr (values , 'dtype' ) and is_bool_dtype (values .dtype ) and
405
- mask is None ):
406
- # Assume np.bool cannot store NaNs
407
- skipna = False
408
- values , _ , _ , _ , _ = _get_values (values , skipna , True , copy = skipna ,
409
- mask = mask , compute_mask = False )
415
+ mask = _maybe_get_mask (values , skipna , mask )
416
+ values , _ , _ , _ = _get_values (values , skipna , mask , fill_value = True ,
417
+ copy = skipna )
410
418
return values .all (axis )
411
419
412
420
@@ -435,8 +443,9 @@ def nansum(values, axis=None, skipna=True, min_count=0, mask=None):
435
443
>>> nanops.nansum(s)
436
444
3.0
437
445
"""
438
- values , mask , dtype , dtype_max , _ = _get_values (values ,
439
- skipna , 0 , mask = mask )
446
+ mask = _maybe_get_mask (values , skipna , mask )
447
+ values , dtype , dtype_max , _ = _get_values (values , skipna , mask ,
448
+ fill_value = 0 )
440
449
dtype_sum = dtype_max
441
450
if is_float_dtype (dtype ):
442
451
dtype_sum = dtype
@@ -475,8 +484,9 @@ def nanmean(values, axis=None, skipna=True, mask=None):
475
484
>>> nanops.nanmean(s)
476
485
1.5
477
486
"""
478
- values , mask , dtype , dtype_max , _ = _get_values (
479
- values , skipna , 0 , mask = mask )
487
+ mask = _get_mask (values , mask )
488
+ values , dtype , dtype_max , _ = _get_values (values , skipna , mask ,
489
+ fill_value = 0 )
480
490
dtype_sum = dtype_max
481
491
dtype_count = np .float64
482
492
if (is_integer_dtype (dtype ) or is_timedelta64_dtype (dtype ) or
@@ -532,7 +542,8 @@ def get_median(x):
532
542
return np .nan
533
543
return np .nanmedian (x [mask ])
534
544
535
- values , mask , dtype , dtype_max , _ = _get_values (values , skipna , mask = mask )
545
+ mask = _get_mask (values , mask )
546
+ values , dtype , dtype_max , _ = _get_values (values , skipna , mask )
536
547
if not is_float_dtype (values ):
537
548
values = values .astype ('f8' )
538
549
values [mask ] = np .nan
@@ -737,8 +748,9 @@ def _nanminmax(meth, fill_value_typ):
737
748
@bottleneck_switch ()
738
749
def reduction (values , axis = None , skipna = True , mask = None ):
739
750
740
- values , mask , dtype , dtype_max , fill_value = _get_values (
741
- values , skipna , fill_value_typ = fill_value_typ , mask = mask )
751
+ mask = _maybe_get_mask (values , skipna , mask )
752
+ values , dtype , dtype_max , fill_value = _get_values (
753
+ values , skipna , mask , fill_value_typ = fill_value_typ )
742
754
743
755
if ((axis is not None and values .shape [axis ] == 0 ) or
744
756
values .size == 0 ):
@@ -785,8 +797,9 @@ def nanargmax(values, axis=None, skipna=True, mask=None):
785
797
>>> nanops.nanargmax(s)
786
798
4
787
799
"""
788
- values , mask , dtype , _ , _ = _get_values (
789
- values , skipna , fill_value_typ = '-inf' , mask = mask )
800
+ mask = _get_mask (values , mask )
801
+ values , dtype , _ , _ = _get_values (
802
+ values , skipna , mask , fill_value_typ = '-inf' )
790
803
result = values .argmax (axis )
791
804
result = _maybe_arg_null_out (result , axis , mask , skipna )
792
805
return result
@@ -815,8 +828,9 @@ def nanargmin(values, axis=None, skipna=True, mask=None):
815
828
>>> nanops.nanargmin(s)
816
829
0
817
830
"""
818
- values , mask , dtype , _ , _ = _get_values (
819
- values , skipna , fill_value_typ = '+inf' , mask = mask )
831
+ mask = _get_mask (values , mask )
832
+ values , dtype , _ , _ = _get_values (
833
+ values , skipna , mask , fill_value_typ = '+inf' )
820
834
result = values .argmin (axis )
821
835
result = _maybe_arg_null_out (result , axis , mask , skipna )
822
836
return result
@@ -1028,6 +1042,9 @@ def nanprod(values, axis=None, skipna=True, min_count=0, mask=None):
1028
1042
1029
1043
def _maybe_arg_null_out (result , axis , mask , skipna ):
1030
1044
# helper function for nanargmin/nanargmax
1045
+ if mask is None :
1046
+ return result
1047
+
1031
1048
if axis is None or not getattr (result , 'ndim' , False ):
1032
1049
if skipna :
1033
1050
if mask .all ():
@@ -1060,6 +1077,9 @@ def _get_counts(mask, axis, dtype=float):
1060
1077
1061
1078
1062
1079
def _maybe_null_out (result , axis , mask , min_count = 1 ):
1080
+ if mask is None :
1081
+ return result
1082
+
1063
1083
if axis is not None and getattr (result , 'ndim' , False ):
1064
1084
null_mask = (mask .shape [axis ] - mask .sum (axis ) - min_count ) < 0
1065
1085
if np .any (null_mask ):
0 commit comments