Skip to content

Commit 51f114b

Browse files
authored
BUG: isna_old with td64, dt64tz, period (#33158)
1 parent cb41651 commit 51f114b

File tree

2 files changed

+42
-61
lines changed

2 files changed

+42
-61
lines changed

pandas/core/dtypes/missing.py

+27-61
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,24 @@
1616
ensure_object,
1717
is_bool_dtype,
1818
is_complex_dtype,
19-
is_datetime64_dtype,
20-
is_datetime64tz_dtype,
2119
is_datetimelike_v_numeric,
2220
is_dtype_equal,
2321
is_extension_array_dtype,
2422
is_float_dtype,
2523
is_integer_dtype,
2624
is_object_dtype,
27-
is_period_dtype,
2825
is_scalar,
2926
is_string_dtype,
3027
is_string_like_dtype,
31-
is_timedelta64_dtype,
3228
needs_i8_conversion,
3329
pandas_dtype,
3430
)
3531
from pandas.core.dtypes.generic import (
3632
ABCDataFrame,
37-
ABCDatetimeArray,
3833
ABCExtensionArray,
3934
ABCIndexClass,
4035
ABCMultiIndex,
4136
ABCSeries,
42-
ABCTimedeltaArray,
4337
)
4438
from pandas.core.dtypes.inference import is_list_like
4539

@@ -139,17 +133,7 @@ def _isna_new(obj):
139133
raise NotImplementedError("isna is not defined for MultiIndex")
140134
elif isinstance(obj, type):
141135
return False
142-
elif isinstance(
143-
obj,
144-
(
145-
ABCSeries,
146-
np.ndarray,
147-
ABCIndexClass,
148-
ABCExtensionArray,
149-
ABCDatetimeArray,
150-
ABCTimedeltaArray,
151-
),
152-
):
136+
elif isinstance(obj, (ABCSeries, np.ndarray, ABCIndexClass, ABCExtensionArray)):
153137
return _isna_ndarraylike(obj)
154138
elif isinstance(obj, ABCDataFrame):
155139
return obj.isna()
@@ -158,7 +142,7 @@ def _isna_new(obj):
158142
elif hasattr(obj, "__array__"):
159143
return _isna_ndarraylike(np.asarray(obj))
160144
else:
161-
return obj is None
145+
return False
162146

163147

164148
def _isna_old(obj):
@@ -189,7 +173,7 @@ def _isna_old(obj):
189173
elif hasattr(obj, "__array__"):
190174
return _isna_ndarraylike_old(np.asarray(obj))
191175
else:
192-
return obj is None
176+
return False
193177

194178

195179
_isna = _isna_new
@@ -224,37 +208,14 @@ def _use_inf_as_na(key):
224208

225209

226210
def _isna_ndarraylike(obj):
227-
is_extension = is_extension_array_dtype(obj)
228-
229-
if not is_extension:
230-
# Avoid accessing `.values` on things like
231-
# PeriodIndex, which may be expensive.
232-
values = getattr(obj, "_values", obj)
233-
else:
234-
values = obj
235-
211+
is_extension = is_extension_array_dtype(obj.dtype)
212+
values = getattr(obj, "_values", obj)
236213
dtype = values.dtype
237214

238215
if is_extension:
239-
if isinstance(obj, (ABCIndexClass, ABCSeries)):
240-
values = obj._values
241-
else:
242-
values = obj
243216
result = values.isna()
244-
elif isinstance(obj, ABCDatetimeArray):
245-
return obj.isna()
246217
elif is_string_dtype(dtype):
247-
# Working around NumPy ticket 1542
248-
shape = values.shape
249-
250-
if is_string_like_dtype(dtype):
251-
# object array of strings
252-
result = np.zeros(values.shape, dtype=bool)
253-
else:
254-
# object array of non-strings
255-
result = np.empty(shape, dtype=bool)
256-
vec = libmissing.isnaobj(values.ravel())
257-
result[...] = vec.reshape(shape)
218+
result = _isna_string_dtype(values, dtype, old=False)
258219

259220
elif needs_i8_conversion(dtype):
260221
# this is the NaT pattern
@@ -274,17 +235,9 @@ def _isna_ndarraylike_old(obj):
274235
dtype = values.dtype
275236

276237
if is_string_dtype(dtype):
277-
# Working around NumPy ticket 1542
278-
shape = values.shape
279-
280-
if is_string_like_dtype(dtype):
281-
result = np.zeros(values.shape, dtype=bool)
282-
else:
283-
result = np.empty(shape, dtype=bool)
284-
vec = libmissing.isnaobj_old(values.ravel())
285-
result[:] = vec.reshape(shape)
238+
result = _isna_string_dtype(values, dtype, old=True)
286239

287-
elif is_datetime64_dtype(dtype):
240+
elif needs_i8_conversion(dtype):
288241
# this is the NaT pattern
289242
result = values.view("i8") == iNaT
290243
else:
@@ -297,6 +250,24 @@ def _isna_ndarraylike_old(obj):
297250
return result
298251

299252

253+
def _isna_string_dtype(values: np.ndarray, dtype: np.dtype, old: bool) -> np.ndarray:
254+
# Working around NumPy ticket 1542
255+
shape = values.shape
256+
257+
if is_string_like_dtype(dtype):
258+
result = np.zeros(values.shape, dtype=bool)
259+
else:
260+
result = np.empty(shape, dtype=bool)
261+
if old:
262+
vec = libmissing.isnaobj_old(values.ravel())
263+
else:
264+
vec = libmissing.isnaobj(values.ravel())
265+
266+
result[...] = vec.reshape(shape)
267+
268+
return result
269+
270+
300271
def notna(obj):
301272
"""
302273
Detect non-missing values for an array-like object.
@@ -556,12 +527,7 @@ def na_value_for_dtype(dtype, compat: bool = True):
556527

557528
if is_extension_array_dtype(dtype):
558529
return dtype.na_value
559-
if (
560-
is_datetime64_dtype(dtype)
561-
or is_datetime64tz_dtype(dtype)
562-
or is_timedelta64_dtype(dtype)
563-
or is_period_dtype(dtype)
564-
):
530+
if needs_i8_conversion(dtype):
565531
return NaT
566532
elif is_float_dtype(dtype):
567533
return np.nan

pandas/tests/dtypes/test_missing.py

+15
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,21 @@ def test_isna_datetime(self):
185185
exp = np.zeros(len(mask), dtype=bool)
186186
tm.assert_numpy_array_equal(mask, exp)
187187

188+
def test_isna_old_datetimelike(self):
189+
# isna_old should work for dt64tz, td64, and period, not just tznaive
190+
dti = pd.date_range("2016-01-01", periods=3)
191+
dta = dti._data
192+
dta[-1] = pd.NaT
193+
expected = np.array([False, False, True], dtype=bool)
194+
195+
objs = [dta, dta.tz_localize("US/Eastern"), dta - dta, dta.to_period("D")]
196+
197+
for obj in objs:
198+
with cf.option_context("mode.use_inf_as_na", True):
199+
result = pd.isna(obj)
200+
201+
tm.assert_numpy_array_equal(result, expected)
202+
188203
@pytest.mark.parametrize(
189204
"value, expected",
190205
[

0 commit comments

Comments
 (0)