def _isna_array(values: ArrayLike, inf_as_na: bool = False): """ Return an array indicating which values of the input array are NaN / NA. Parameters ---------- obj: ndarray or ExtensionArray The input array whose elements are to be checked. inf_as_na: bool Whether or not to treat infinite values as NA. Returns ------- array-like Array of boolean values denoting the NA status of each element. """ dtype = values.dtype if is_extension_array_dtype(dtype): if inf_as_na and is_categorical_dtype(dtype): result = libmissing.isnaobj_old(values.to_numpy()) else: result = values.isna() elif is_string_dtype(dtype): result = _isna_string_dtype(values, dtype, inf_as_na=inf_as_na) elif needs_i8_conversion(dtype): # this is the NaT pattern result = values.view("i8") == iNaT else: if inf_as_na: result = ~np.isfinite(values) else: result = np.isnan(values) return result
def _isna_array(values: ArrayLike, inf_as_na: bool = False): """ Return an array indicating which values of the input array are NaN / NA. Parameters ---------- obj: ndarray or ExtensionArray The input array whose elements are to be checked. inf_as_na: bool Whether or not to treat infinite values as NA. Returns ------- array-like Array of boolean values denoting the NA status of each element. """ dtype = values.dtype if is_extension_array_dtype(dtype): if inf_as_na and is_categorical_dtype(dtype): # error: Item "ndarray" of "Union[ExtensionArray, ndarray]" has no attribute # "to_numpy" result = libmissing.isnaobj_old( values.to_numpy() # type: ignore[union-attr] ) else: # error: Item "ndarray" of "Union[ExtensionArray, ndarray]" has no attribute # "isna" result = values.isna() # type: ignore[union-attr] elif is_string_dtype(dtype): # error: Argument 1 to "_isna_string_dtype" has incompatible type # "ExtensionArray"; expected "ndarray" # error: Argument 2 to "_isna_string_dtype" has incompatible type # "ExtensionDtype"; expected "dtype[Any]" result = _isna_string_dtype( values, dtype, inf_as_na=inf_as_na # type: ignore[arg-type] ) elif needs_i8_conversion(dtype): # this is the NaT pattern result = values.view("i8") == iNaT else: if inf_as_na: # error: Argument 1 to "__call__" of "ufunc" has incompatible type # "ExtensionArray"; expected "Union[Union[int, float, complex, str, bytes, # generic], Sequence[Union[int, float, complex, str, bytes, generic]], # Sequence[Sequence[Any]], _SupportsArray]" result = ~np.isfinite(values) # type: ignore[arg-type] else: # error: Argument 1 to "__call__" of "ufunc" has incompatible type # "ExtensionArray"; expected "Union[Union[int, float, complex, str, bytes, # generic], Sequence[Union[int, float, complex, str, bytes, generic]], # Sequence[Sequence[Any]], _SupportsArray]" result = np.isnan(values) # type: ignore[arg-type] return result
def _isna_array(values: ArrayLike, inf_as_na: bool = False): """ Return an array indicating which values of the input array are NaN / NA. Parameters ---------- obj: ndarray or ExtensionArray The input array whose elements are to be checked. inf_as_na: bool Whether or not to treat infinite values as NA. Returns ------- array-like Array of boolean values denoting the NA status of each element. """ dtype = values.dtype if not isinstance(values, np.ndarray): # i.e. ExtensionArray if inf_as_na and is_categorical_dtype(dtype): result = libmissing.isnaobj(values.to_numpy(), inf_as_na=inf_as_na) else: # error: Incompatible types in assignment (expression has type # "Union[ndarray[Any, Any], ExtensionArraySupportsAnyAll]", variable has # type "ndarray[Any, dtype[bool_]]") result = values.isna() # type: ignore[assignment] elif is_string_or_object_np_dtype(values.dtype): result = _isna_string_dtype(values, inf_as_na=inf_as_na) elif needs_i8_conversion(dtype): # this is the NaT pattern result = values.view("i8") == iNaT else: if inf_as_na: result = ~np.isfinite(values) else: result = np.isnan(values) return result
def na_accum_func(values: ArrayLike, accum_func, skipna: bool) -> ArrayLike: """ Cumulative function with skipna support. Parameters ---------- values : np.ndarray or ExtensionArray accum_func : {np.cumprod, np.maximum.accumulate, np.cumsum, np.minimum.accumulate} skipna : bool Returns ------- np.ndarray or ExtensionArray """ mask_a, mask_b = { np.cumprod: (1.0, np.nan), np.maximum.accumulate: (-np.inf, np.nan), np.cumsum: (0.0, np.nan), np.minimum.accumulate: (np.inf, np.nan), }[accum_func] # We will be applying this function to block values if values.dtype.kind in ["m", "M"]: # GH#30460, GH#29058 # numpy 1.18 started sorting NaTs at the end instead of beginning, # so we need to work around to maintain backwards-consistency. orig_dtype = values.dtype # We need to define mask before masking NaTs mask = isna(values) if accum_func == np.minimum.accumulate: # Note: the accum_func comparison fails as an "is" comparison y = values.view("i8") y[mask] = np.iinfo(np.int64).max changed = True else: y = values changed = False result = accum_func(y.view("i8"), axis=0) if skipna: result[mask] = iNaT elif accum_func == np.minimum.accumulate: # Restore NaTs that we masked previously nz = (~np.asarray(mask)).nonzero()[0] if len(nz): # everything up to the first non-na entry stays NaT result[: nz[0]] = iNaT if changed: # restore NaT elements y[mask] = iNaT # TODO: could try/finally for this? if isinstance(values, np.ndarray): result = result.view(orig_dtype) else: # DatetimeArray result = type(values)._from_sequence(result, dtype=orig_dtype) elif skipna and not issubclass(values.dtype.type, (np.integer, np.bool_)): vals = values.copy() mask = isna(vals) vals[mask] = mask_a result = accum_func(vals, axis=0) result[mask] = mask_b else: result = accum_func(values, axis=0) return result