Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/core/dtypes/missing.py: 23%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

264 statements  

1""" 

2missing types & inference 

3""" 

4 

5from __future__ import annotations 

6 

7from decimal import Decimal 

8from typing import ( 

9 TYPE_CHECKING, 

10 overload, 

11) 

12import warnings 

13 

14import numpy as np 

15 

16from pandas._libs import lib 

17import pandas._libs.missing as libmissing 

18from pandas._libs.tslibs import ( 

19 NaT, 

20 iNaT, 

21) 

22from pandas.util._decorators import set_module 

23 

24from pandas.core.dtypes.common import ( 

25 DT64NS_DTYPE, 

26 TD64NS_DTYPE, 

27 ensure_object, 

28 is_scalar, 

29 is_string_or_object_np_dtype, 

30) 

31from pandas.core.dtypes.dtypes import ( 

32 CategoricalDtype, 

33 DatetimeTZDtype, 

34 ExtensionDtype, 

35 IntervalDtype, 

36 PeriodDtype, 

37) 

38from pandas.core.dtypes.generic import ( 

39 ABCDataFrame, 

40 ABCExtensionArray, 

41 ABCIndex, 

42 ABCMultiIndex, 

43 ABCSeries, 

44) 

45from pandas.core.dtypes.inference import is_list_like 

46 

47if TYPE_CHECKING: 

48 from re import Pattern 

49 

50 from pandas._libs.missing import NAType 

51 from pandas._libs.tslibs import NaTType 

52 from pandas._typing import ( 

53 ArrayLike, 

54 DtypeObj, 

55 NDFrame, 

56 NDFrameT, 

57 Scalar, 

58 npt, 

59 ) 

60 

61 from pandas import Series 

62 from pandas.core.indexes.base import Index 

63 

64 

65isposinf_scalar = libmissing.isposinf_scalar 

66isneginf_scalar = libmissing.isneginf_scalar 

67 

68_dtype_object = np.dtype("object") 

69_dtype_str = np.dtype(str) 

70 

71 

72@overload 

73def isna(obj: Scalar | Pattern | NAType | NaTType) -> bool: ... 

74 

75 

76@overload 

77def isna( 

78 obj: ArrayLike | Index | list, 

79) -> npt.NDArray[np.bool_]: ... 

80 

81 

82@overload 

83def isna(obj: NDFrameT) -> NDFrameT: ... 

84 

85 

86# handle unions 

87@overload 

88def isna( 

89 obj: NDFrameT | ArrayLike | Index | list, 

90) -> NDFrameT | npt.NDArray[np.bool_]: ... 

91 

92 

93@overload 

94def isna(obj: object) -> bool | npt.NDArray[np.bool_] | NDFrame: ... 

95 

96 

97@set_module("pandas") 

98def isna(obj: object) -> bool | npt.NDArray[np.bool_] | NDFrame: 

99 """ 

100 Detect missing values for an array-like object. 

101 

102 This function takes a scalar or array-like object and indicates 

103 whether values are missing (``NaN`` in numeric arrays, ``None`` or ``NaN`` 

104 in object arrays, ``NaT`` in datetimelike). 

105 

106 Parameters 

107 ---------- 

108 obj : scalar or array-like 

109 Object to check for null or missing values. 

110 

111 Returns 

112 ------- 

113 bool or array-like of bool 

114 For scalar input, returns a scalar boolean. 

115 For array input, returns an array of boolean indicating whether each 

116 corresponding element is missing. 

117 

118 See Also 

119 -------- 

120 notna : Boolean inverse of pandas.isna. 

121 Series.isna : Detect missing values in a Series. 

122 DataFrame.isna : Detect missing values in a DataFrame. 

123 Index.isna : Detect missing values in an Index. 

124 

125 Examples 

126 -------- 

127 Scalar arguments (including strings) result in a scalar boolean. 

128 

129 >>> pd.isna("dog") 

130 False 

131 

132 >>> pd.isna(pd.NA) 

133 True 

134 

135 >>> pd.isna(np.nan) 

136 True 

137 

138 ndarrays result in an ndarray of booleans. 

139 

140 >>> array = np.array([[1, np.nan, 3], [4, 5, np.nan]]) 

141 >>> array 

142 array([[ 1., nan, 3.], 

143 [ 4., 5., nan]]) 

144 >>> pd.isna(array) 

145 array([[False, True, False], 

146 [False, False, True]]) 

147 

148 For indexes, an ndarray of booleans is returned. 

149 

150 >>> index = pd.DatetimeIndex(["2017-07-05", "2017-07-06", None, "2017-07-08"]) 

151 >>> index 

152 DatetimeIndex(['2017-07-05', '2017-07-06', 'NaT', '2017-07-08'], 

153 dtype='datetime64[us]', freq=None) 

154 >>> pd.isna(index) 

155 array([False, False, True, False]) 

156 

157 For Series and DataFrame, the same type is returned, containing booleans. 

158 

159 >>> df = pd.DataFrame([["ant", "bee", "cat"], ["dog", None, "fly"]]) 

160 >>> df 

161 0 1 2 

162 0 ant bee cat 

163 1 dog NaN fly 

164 >>> pd.isna(df) 

165 0 1 2 

166 0 False False False 

167 1 False True False 

168 

169 >>> pd.isna(df[1]) 

170 0 False 

171 1 True 

172 Name: 1, dtype: bool 

173 """ 

174 return _isna(obj) 

175 

176 

177isnull = isna 

178 

179 

180def _isna(obj): 

181 """ 

182 Detect missing values, treating None, NaN or NA as null. 

183 

184 Parameters 

185 ---------- 

186 obj: ndarray or object value 

187 Input array or scalar value. 

188 

189 Returns 

190 ------- 

191 boolean ndarray or boolean 

192 """ 

193 if is_scalar(obj): 

194 return libmissing.checknull(obj) 

195 elif isinstance(obj, ABCMultiIndex): 

196 raise NotImplementedError("isna is not defined for MultiIndex") 

197 elif isinstance(obj, type): 

198 return False 

199 elif isinstance(obj, (np.ndarray, ABCExtensionArray)): 

200 return _isna_array(obj) 

201 elif isinstance(obj, ABCIndex): 

202 # Try to use cached isna, which also short-circuits for integer dtypes 

203 # and avoids materializing RangeIndex._values 

204 if not obj._can_hold_na: 

205 return obj.isna() 

206 return _isna_array(obj._values) 

207 

208 elif isinstance(obj, ABCSeries): 

209 result = _isna_array(obj._values) 

210 # box 

211 result = obj._constructor(result, index=obj.index, name=obj.name, copy=False) 

212 return result 

213 elif isinstance(obj, ABCDataFrame): 

214 return obj.isna() 

215 elif isinstance(obj, list): 

216 return _isna_array(np.asarray(obj, dtype=object)) 

217 elif hasattr(obj, "__array__"): 

218 return _isna_array(np.asarray(obj)) 

219 else: 

220 return False 

221 

222 

223def _isna_array(values: ArrayLike) -> npt.NDArray[np.bool_] | NDFrame: 

224 """ 

225 Return an array indicating which values of the input array are NaN / NA. 

226 

227 Parameters 

228 ---------- 

229 obj: ndarray or ExtensionArray 

230 The input array whose elements are to be checked. 

231 

232 Returns 

233 ------- 

234 array-like 

235 Array of boolean values denoting the NA status of each element. 

236 """ 

237 dtype = values.dtype 

238 result: npt.NDArray[np.bool_] | NDFrame 

239 

240 if not isinstance(values, np.ndarray): 

241 # i.e. ExtensionArray 

242 # error: Incompatible types in assignment (expression has type 

243 # "Union[ndarray[Any, Any], ExtensionArraySupportsAnyAll]", variable has 

244 # type "ndarray[Any, dtype[bool_]]") 

245 result = values.isna() # type: ignore[assignment] 

246 elif isinstance(values, np.rec.recarray): 

247 # GH 48526 

248 result = _isna_recarray_dtype(values) 

249 elif is_string_or_object_np_dtype(values.dtype): 

250 result = _isna_string_dtype(values) 

251 elif dtype.kind in "mM": 

252 # this is the NaT pattern 

253 result = values.view("i8") == iNaT 

254 else: 

255 result = np.isnan(values) 

256 

257 return result 

258 

259 

260def _isna_string_dtype(values: np.ndarray) -> npt.NDArray[np.bool_]: 

261 # Working around NumPy ticket 1542 

262 dtype = values.dtype 

263 

264 if dtype.kind in ("S", "U"): 

265 result = np.zeros(values.shape, dtype=bool) 

266 elif values.ndim in {1, 2}: 

267 result = libmissing.isnaobj(values) 

268 else: 

269 # 0-D, reached via e.g. mask_missing 

270 result = libmissing.isnaobj(values.ravel()) 

271 result = result.reshape(values.shape) 

272 

273 return result 

274 

275 

276def _isna_recarray_dtype(values: np.rec.recarray) -> npt.NDArray[np.bool_]: 

277 result = np.zeros(values.shape, dtype=bool) 

278 for i, record in enumerate(values): 

279 record_as_array = np.array(record.tolist()) 

280 does_record_contain_nan = isna_all(record_as_array) 

281 result[i] = np.any(does_record_contain_nan) 

282 

283 return result 

284 

285 

286@overload 

287def notna(obj: Scalar | Pattern | NAType | NaTType) -> bool: ... 

288 

289 

290@overload 

291def notna( 

292 obj: ArrayLike | Index | list, 

293) -> npt.NDArray[np.bool_]: ... 

294 

295 

296@overload 

297def notna(obj: NDFrameT) -> NDFrameT: ... 

298 

299 

300# handle unions 

301@overload 

302def notna( 

303 obj: NDFrameT | ArrayLike | Index | list, 

304) -> NDFrameT | npt.NDArray[np.bool_]: ... 

305 

306 

307@overload 

308def notna(obj: object) -> bool | npt.NDArray[np.bool_] | NDFrame: ... 

309 

310 

311@set_module("pandas") 

312def notna(obj: object) -> bool | npt.NDArray[np.bool_] | NDFrame: 

313 """ 

314 Detect non-missing values for an array-like object. 

315 

316 This function takes a scalar or array-like object and indicates 

317 whether values are valid (not missing, which is ``NaN`` in numeric 

318 arrays, ``None`` or ``NaN`` in object arrays, ``NaT`` in datetimelike). 

319 

320 Parameters 

321 ---------- 

322 obj : array-like or object value 

323 Object to check for *not* null or *non*-missing values. 

324 

325 Returns 

326 ------- 

327 bool or array-like of bool 

328 For scalar input, returns a scalar boolean. 

329 For array input, returns an array of boolean indicating whether each 

330 corresponding element is valid. 

331 

332 See Also 

333 -------- 

334 isna : Boolean inverse of pandas.notna. 

335 Series.notna : Detect valid values in a Series. 

336 DataFrame.notna : Detect valid values in a DataFrame. 

337 Index.notna : Detect valid values in an Index. 

338 

339 Examples 

340 -------- 

341 Scalar arguments (including strings) result in a scalar boolean. 

342 

343 >>> pd.notna("dog") 

344 True 

345 

346 >>> pd.notna(pd.NA) 

347 False 

348 

349 >>> pd.notna(np.nan) 

350 False 

351 

352 ndarrays result in an ndarray of booleans. 

353 

354 >>> array = np.array([[1, np.nan, 3], [4, 5, np.nan]]) 

355 >>> array 

356 array([[ 1., nan, 3.], 

357 [ 4., 5., nan]]) 

358 >>> pd.notna(array) 

359 array([[ True, False, True], 

360 [ True, True, False]]) 

361 

362 For indexes, an ndarray of booleans is returned. 

363 

364 >>> index = pd.DatetimeIndex(["2017-07-05", "2017-07-06", None, "2017-07-08"]) 

365 >>> index 

366 DatetimeIndex(['2017-07-05', '2017-07-06', 'NaT', '2017-07-08'], 

367 dtype='datetime64[us]', freq=None) 

368 >>> pd.notna(index) 

369 array([ True, True, False, True]) 

370 

371 For Series and DataFrame, the same type is returned, containing booleans. 

372 

373 >>> df = pd.DataFrame([["ant", "bee", "cat"], ["dog", None, "fly"]]) 

374 >>> df 

375 0 1 2 

376 0 ant bee cat 

377 1 dog NaN fly 

378 >>> pd.notna(df) 

379 0 1 2 

380 0 True True True 

381 1 True False True 

382 

383 >>> pd.notna(df[1]) 

384 0 True 

385 1 False 

386 Name: 1, dtype: bool 

387 """ 

388 res = isna(obj) 

389 if isinstance(res, bool): 

390 return not res 

391 return ~res 

392 

393 

394notnull = notna 

395 

396 

397def array_equivalent( 

398 left, 

399 right, 

400 strict_nan: bool = False, 

401 dtype_equal: bool = False, 

402) -> bool: 

403 """ 

404 True if two arrays, left and right, have equal non-NaN elements, and NaNs 

405 in corresponding locations. False otherwise. It is assumed that left and 

406 right are NumPy arrays of the same dtype. The behavior of this function 

407 (particularly with respect to NaNs) is not defined if the dtypes are 

408 different. 

409 

410 Parameters 

411 ---------- 

412 left, right : ndarrays 

413 strict_nan : bool, default False 

414 If True, consider NaN and None to be different. 

415 dtype_equal : bool, default False 

416 Whether `left` and `right` are known to have the same dtype 

417 according to `is_dtype_equal`. Some methods like `BlockManager.equals`. 

418 require that the dtypes match. Setting this to ``True`` can improve 

419 performance, but will give different results for arrays that are 

420 equal but different dtypes. 

421 

422 Returns 

423 ------- 

424 b : bool 

425 Returns True if the arrays are equivalent. 

426 

427 Examples 

428 -------- 

429 >>> array_equivalent(np.array([1, 2, np.nan]), np.array([1, 2, np.nan])) 

430 np.True_ 

431 >>> array_equivalent(np.array([1, np.nan, 2]), np.array([1, 2, np.nan])) 

432 np.False_ 

433 """ 

434 left, right = np.asarray(left), np.asarray(right) 

435 

436 # shape compat 

437 if left.shape != right.shape: 

438 return False 

439 

440 if dtype_equal: 

441 # fastpath when we require that the dtypes match (Block.equals) 

442 if left.dtype.kind in "fc": 

443 return _array_equivalent_float(left, right) 

444 elif left.dtype.kind in "mM": 

445 return _array_equivalent_datetimelike(left, right) 

446 elif is_string_or_object_np_dtype(left.dtype): 

447 # TODO: fastpath for pandas' StringDtype 

448 return _array_equivalent_object(left, right, strict_nan) 

449 else: 

450 return np.array_equal(left, right) 

451 

452 # Slow path when we allow comparing different dtypes. 

453 # Object arrays can contain None, NaN and NaT. 

454 # string dtypes must be come to this path for NumPy 1.7.1 compat 

455 if left.dtype.kind in "OSU" or right.dtype.kind in "OSU": 

456 # Note: `in "OSU"` is non-trivially faster than `in ["O", "S", "U"]` 

457 # or `in ("O", "S", "U")` 

458 return _array_equivalent_object(left, right, strict_nan) 

459 

460 # NaNs can occur in float and complex arrays. 

461 if left.dtype.kind in "fc": 

462 if not (left.size and right.size): 

463 return True 

464 return ((left == right) | (isna(left) & isna(right))).all() 

465 

466 elif left.dtype.kind in "mM" or right.dtype.kind in "mM": 

467 # datetime64, timedelta64, Period 

468 if left.dtype != right.dtype: 

469 return False 

470 

471 left = left.view("i8") 

472 right = right.view("i8") 

473 

474 # if we have structured dtypes, compare first 

475 if ( 

476 left.dtype.type is np.void or right.dtype.type is np.void 

477 ) and left.dtype != right.dtype: 

478 return False 

479 

480 return np.array_equal(left, right) 

481 

482 

483def _array_equivalent_float(left: np.ndarray, right: np.ndarray) -> bool: 

484 return bool(((left == right) | (np.isnan(left) & np.isnan(right))).all()) 

485 

486 

487def _array_equivalent_datetimelike(left: np.ndarray, right: np.ndarray) -> bool: 

488 return np.array_equal(left.view("i8"), right.view("i8")) 

489 

490 

491def _array_equivalent_object( 

492 left: np.ndarray, right: np.ndarray, strict_nan: bool 

493) -> bool: 

494 left = ensure_object(left) 

495 right = ensure_object(right) 

496 

497 mask: npt.NDArray[np.bool_] | None = None 

498 if strict_nan: 

499 mask = isna(left) & isna(right) 

500 if not mask.any(): 

501 mask = None 

502 

503 try: 

504 if mask is None: 

505 return lib.array_equivalent_object(left, right) 

506 if not lib.array_equivalent_object(left[~mask], right[~mask]): 

507 return False 

508 left_remaining = left[mask] 

509 right_remaining = right[mask] 

510 except ValueError: 

511 # can raise a ValueError if left and right cannot be 

512 # compared (e.g. nested arrays) 

513 left_remaining = left 

514 right_remaining = right 

515 

516 for left_value, right_value in zip(left_remaining, right_remaining, strict=True): 

517 if left_value is NaT and right_value is not NaT: 

518 return False 

519 

520 elif left_value is libmissing.NA and right_value is not libmissing.NA: 

521 return False 

522 

523 elif isinstance(left_value, float) and np.isnan(left_value): 

524 if not isinstance(right_value, float) or not np.isnan(right_value): 

525 return False 

526 else: 

527 with warnings.catch_warnings(): 

528 # suppress numpy's "elementwise comparison failed" 

529 warnings.simplefilter("ignore", DeprecationWarning) 

530 try: 

531 if np.any(np.asarray(left_value != right_value)): 

532 return False 

533 except TypeError as err: 

534 if "boolean value of NA is ambiguous" in str(err): 

535 return False 

536 raise 

537 except ValueError: 

538 # numpy can raise a ValueError if left and right cannot be 

539 # compared (e.g. nested arrays) 

540 return False 

541 return True 

542 

543 

544def array_equals(left: ArrayLike, right: ArrayLike) -> bool: 

545 """ 

546 ExtensionArray-compatible implementation of array_equivalent. 

547 """ 

548 if left.dtype != right.dtype: 

549 return False 

550 elif isinstance(left, ABCExtensionArray): 

551 return left.equals(right) 

552 else: 

553 return array_equivalent(left, right, dtype_equal=True) 

554 

555 

556def infer_fill_value(val): 

557 """ 

558 infer the fill value for the nan/NaT from the provided 

559 scalar/ndarray/list-like if we are a NaT, return the correct dtyped 

560 element to provide proper block construction 

561 """ 

562 if not is_list_like(val): 

563 val = [val] 

564 val = np.asarray(val) 

565 if val.dtype.kind in "mM": 

566 return np.array("NaT", dtype=val.dtype) 

567 elif val.dtype == object: 

568 dtype = lib.infer_dtype(ensure_object(val), skipna=False) 

569 if dtype in ["datetime", "datetime64"]: 

570 return np.array("NaT", dtype=DT64NS_DTYPE) 

571 elif dtype in ["timedelta", "timedelta64"]: 

572 return np.array("NaT", dtype=TD64NS_DTYPE) 

573 return np.array(np.nan, dtype=object) 

574 elif val.dtype.kind == "U": 

575 return np.array(np.nan, dtype=val.dtype) 

576 return np.nan 

577 

578 

579def construct_1d_array_from_inferred_fill_value( 

580 value: object, length: int 

581) -> ArrayLike: 

582 # Find our empty_value dtype by constructing an array 

583 # from our value and doing a .take on it 

584 from pandas.core.algorithms import take_nd 

585 from pandas.core.construction import sanitize_array 

586 from pandas.core.indexes.base import Index 

587 

588 arr = sanitize_array(value, Index(range(1)), copy=False) 

589 taker = -1 * np.ones(length, dtype=np.intp) 

590 return take_nd(arr, taker) 

591 

592 

593def maybe_fill(arr: np.ndarray) -> np.ndarray: 

594 """ 

595 Fill numpy.ndarray with NaN, unless we have an integer or boolean dtype. 

596 """ 

597 if arr.dtype.kind not in "iub": 

598 arr.fill(np.nan) 

599 return arr 

600 

601 

602def na_value_for_dtype(dtype: DtypeObj, compat: bool = True): 

603 """ 

604 Return a dtype compat na value 

605 

606 Parameters 

607 ---------- 

608 dtype : string / dtype 

609 compat : bool, default True 

610 

611 Returns 

612 ------- 

613 np.dtype or a pandas dtype 

614 

615 Examples 

616 -------- 

617 >>> na_value_for_dtype(np.dtype("int64")) 

618 0 

619 >>> na_value_for_dtype(np.dtype("int64"), compat=False) 

620 nan 

621 >>> na_value_for_dtype(np.dtype("float64")) 

622 nan 

623 >>> na_value_for_dtype(np.dtype("complex128")) 

624 nan 

625 >>> na_value_for_dtype(np.dtype("bool")) 

626 False 

627 >>> na_value_for_dtype(np.dtype("datetime64[ns]")) 

628 np.datetime64('NaT','ns') 

629 """ 

630 

631 if isinstance(dtype, ExtensionDtype): 

632 return dtype.na_value 

633 elif dtype.kind in "mM": 

634 unit = np.datetime_data(dtype)[0] 

635 return dtype.type("NaT", unit) 

636 elif dtype.kind in "fc": 

637 return np.nan 

638 elif dtype.kind in "iu": 

639 if compat: 

640 return 0 

641 return np.nan 

642 elif dtype.kind == "b": 

643 if compat: 

644 return False 

645 return np.nan 

646 return np.nan 

647 

648 

649def remove_na_arraylike(arr: Series | Index | np.ndarray): 

650 """ 

651 Return array-like containing only true/non-NaN values, possibly empty. 

652 """ 

653 if isinstance(arr.dtype, ExtensionDtype): 

654 return arr[notna(arr)] 

655 else: 

656 return arr[notna(np.asarray(arr))] 

657 

658 

659def is_valid_na_for_dtype(obj, dtype: DtypeObj) -> bool: 

660 """ 

661 isna check that excludes incompatible dtypes 

662 

663 Parameters 

664 ---------- 

665 obj : object 

666 dtype : np.datetime64, np.timedelta64, DatetimeTZDtype, or PeriodDtype 

667 

668 Returns 

669 ------- 

670 bool 

671 """ 

672 if not lib.is_scalar(obj) or not isna(obj): 

673 return False 

674 elif dtype.kind == "M": 

675 if isinstance(dtype, np.dtype): 

676 # i.e. not tzaware 

677 return not isinstance(obj, (np.timedelta64, Decimal)) 

678 # we have to rule out tznaive dt64("NaT") 

679 return not isinstance(obj, (np.timedelta64, np.datetime64, Decimal)) 

680 elif dtype.kind == "m": 

681 return not isinstance(obj, (np.datetime64, Decimal)) 

682 elif dtype.kind in "iufc": 

683 # Numeric 

684 return obj is not NaT and not isinstance(obj, (np.datetime64, np.timedelta64)) 

685 elif dtype.kind == "b": 

686 # We allow pd.NA, None, np.nan in BooleanArray (same as IntervalDtype) 

687 return lib.is_float(obj) or obj is None or obj is libmissing.NA 

688 

689 elif dtype == _dtype_str: 

690 # numpy string dtypes to avoid float np.nan 

691 return not isinstance(obj, (np.datetime64, np.timedelta64, Decimal, float)) 

692 

693 elif dtype == _dtype_object: 

694 # This is needed for Categorical, but is kind of weird 

695 return True 

696 

697 elif isinstance(dtype, PeriodDtype): 

698 return not isinstance(obj, (np.datetime64, np.timedelta64, Decimal)) 

699 

700 elif isinstance(dtype, IntervalDtype): 

701 return lib.is_float(obj) or obj is None or obj is libmissing.NA 

702 

703 elif isinstance(dtype, CategoricalDtype): 

704 return is_valid_na_for_dtype(obj, dtype.categories.dtype) 

705 

706 # fallback, default to allowing NaN, None, NA, NaT 

707 return not isinstance(obj, (np.datetime64, np.timedelta64, Decimal)) 

708 

709 

710def isna_all(arr: ArrayLike) -> bool: 

711 """ 

712 Optimized equivalent to isna(arr).all() 

713 """ 

714 total_len = len(arr) 

715 

716 # Usually it's enough to check but a small fraction of values to see if 

717 # a block is NOT null, chunks should help in such cases. 

718 # parameters 1000 and 40 were chosen arbitrarily 

719 chunk_len = max(total_len // 40, 1000) 

720 

721 dtype = arr.dtype 

722 if lib.is_np_dtype(dtype, "f"): 

723 checker = np.isnan 

724 

725 elif (lib.is_np_dtype(dtype, "mM")) or isinstance( 

726 dtype, (DatetimeTZDtype, PeriodDtype) 

727 ): 

728 # error: Incompatible types in assignment (expression has type 

729 # "Callable[[Any], Any]", variable has type "ufunc") 

730 checker = lambda x: np.asarray(x.view("i8")) == iNaT # type: ignore[assignment] 

731 

732 else: 

733 # error: Incompatible types in assignment (expression has type "Callable[[Any], 

734 # Any]", variable has type "ufunc") 

735 checker = _isna_array # type: ignore[assignment] 

736 

737 return all( 

738 checker(arr[i : i + chunk_len]).all() for i in range(0, total_len, chunk_len) 

739 )