Skip to content

Commit 23438cf

Browse files
committed
PERF: O(n) speedup in any/all by re-enabling short-circuiting for bool case
1 parent 10954bd commit 23438cf

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

asv_bench/benchmarks/series_methods.py

+26
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,30 @@ def time_series_datetimeindex_repr(self):
201201
getattr(self.s, 'a', None)
202202

203203

204+
class All(object):
205+
206+
params = [[10**3, 10**6], ['fast', 'slow']]
207+
param_names = ['N', 'case']
208+
209+
def setup(self, N, case):
210+
val = case != 'fast'
211+
self.s = Series([val] * N)
212+
213+
def time_all(self, N, case):
214+
self.s.all()
215+
216+
217+
class Any(object):
218+
219+
params = [[10**3, 10**6], ['fast', 'slow']]
220+
param_names = ['N', 'case']
221+
222+
def setup(self, N, case):
223+
val = case == 'fast'
224+
self.s = Series([val] * N)
225+
226+
def time_any(self, N, case):
227+
self.s.any()
228+
229+
204230
from .pandas_vb_common import setup # noqa: F401

pandas/core/nanops.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,13 @@ def _get_fill_value(dtype, fill_value=None, fill_value_typ=None):
201201

202202

203203
def _get_values(values, skipna, fill_value=None, fill_value_typ=None,
204-
isfinite=False, copy=True, mask=None):
204+
isfinite=False, copy=True, mask=None, compute_mask=True):
205205
""" utility to get the values view, mask, dtype
206206
if necessary copy and mask using the specified fill_value
207207
copy = True will force the copy
208208
"""
209+
if skipna:
210+
compute_mask = True
209211

210212
if is_datetime64tz_dtype(values):
211213
# com.values_from_object returns M8[ns] dtype instead of tz-aware,
@@ -216,7 +218,7 @@ def _get_values(values, skipna, fill_value=None, fill_value_typ=None,
216218
values = com.values_from_object(values)
217219
dtype = values.dtype
218220

219-
if mask is None:
221+
if mask is None and compute_mask:
220222
if isfinite:
221223
mask = _isfinite(values)
222224
else:
@@ -362,8 +364,12 @@ def nanany(values, axis=None, skipna=True, mask=None):
362364
>>> nanops.nanany(s)
363365
False
364366
"""
365-
values, mask, dtype, _, _ = _get_values(values, skipna, False, copy=skipna,
366-
mask=mask)
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)
367373
return values.any(axis)
368374

369375

@@ -395,8 +401,12 @@ def nanall(values, axis=None, skipna=True, mask=None):
395401
>>> nanops.nanall(s)
396402
False
397403
"""
398-
values, mask, dtype, _, _ = _get_values(values, skipna, True, copy=skipna,
399-
mask=mask)
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)
400410
return values.all(axis)
401411

402412

0 commit comments

Comments
 (0)