|
9 | 9 |
|
10 | 10 | from pandas._libs import lib
|
11 | 11 | import pandas._libs.missing as libmissing
|
12 |
| -from pandas._libs.tslibs import NaT, iNaT |
| 12 | +from pandas._libs.tslibs import NaT, Period, iNaT |
13 | 13 | from pandas._typing import ArrayLike, DtypeObj
|
14 | 14 |
|
15 | 15 | from pandas.core.dtypes.common import (
|
|
43 | 43 | isposinf_scalar = libmissing.isposinf_scalar
|
44 | 44 | isneginf_scalar = libmissing.isneginf_scalar
|
45 | 45 |
|
| 46 | +nan_checker = np.isnan |
| 47 | +INF_AS_NA = False |
| 48 | + |
46 | 49 |
|
47 | 50 | def isna(obj):
|
48 | 51 | """
|
@@ -188,6 +191,12 @@ def _use_inf_as_na(key):
|
188 | 191 | """
|
189 | 192 | inf_as_na = get_option(key)
|
190 | 193 | globals()["_isna"] = partial(_isna, inf_as_na=inf_as_na)
|
| 194 | + if inf_as_na: |
| 195 | + globals()["nan_checker"] = lambda x: ~np.isfinite(x) |
| 196 | + globals()["INF_AS_NA"] = True |
| 197 | + else: |
| 198 | + globals()["nan_checker"] = np.isnan |
| 199 | + globals()["INF_AS_NA"] = False |
191 | 200 |
|
192 | 201 |
|
193 | 202 | def _isna_ndarraylike(obj, inf_as_na: bool = False):
|
@@ -602,3 +611,31 @@ def is_valid_nat_for_dtype(obj, dtype: DtypeObj) -> bool:
|
602 | 611 |
|
603 | 612 | # must be PeriodDType
|
604 | 613 | return not isinstance(obj, (np.datetime64, np.timedelta64))
|
| 614 | + |
| 615 | + |
| 616 | +def isna_all(arr: ArrayLike) -> bool: |
| 617 | + """ |
| 618 | + Optimized equivalent to isna(arr).all() |
| 619 | + """ |
| 620 | + total_len = len(arr) |
| 621 | + |
| 622 | + # Usually it's enough to check but a small fraction of values to see if |
| 623 | + # a block is NOT null, chunks should help in such cases. |
| 624 | + # parameters 1000 and 40 were chosen arbitrarily |
| 625 | + chunk_len = max(total_len // 40, 1000) |
| 626 | + |
| 627 | + dtype = arr.dtype |
| 628 | + if dtype.kind == "f": |
| 629 | + checker = nan_checker |
| 630 | + |
| 631 | + elif dtype.kind in ["m", "M"] or dtype.type is Period: |
| 632 | + checker = lambda x: np.asarray(x.view("i8")) == iNaT |
| 633 | + |
| 634 | + else: |
| 635 | + checker = lambda x: _isna_ndarraylike(x, inf_as_na=INF_AS_NA) |
| 636 | + |
| 637 | + for i in range(0, total_len, chunk_len): |
| 638 | + if not checker(arr[i : i + chunk_len]).all(): |
| 639 | + return False |
| 640 | + |
| 641 | + return True |
0 commit comments