652 lines
20 KiB
Python
652 lines
20 KiB
Python
![]() |
from contextlib import nullcontext
|
||
|
from datetime import datetime
|
||
|
from decimal import Decimal
|
||
|
|
||
|
import numpy as np
|
||
|
import pytest
|
||
|
|
||
|
from pandas._config import config as cf
|
||
|
|
||
|
from pandas._libs import missing as libmissing
|
||
|
from pandas._libs.tslibs import iNaT, is_null_datetimelike
|
||
|
|
||
|
from pandas.core.dtypes.common import is_scalar
|
||
|
from pandas.core.dtypes.dtypes import DatetimeTZDtype, IntervalDtype, PeriodDtype
|
||
|
from pandas.core.dtypes.missing import (
|
||
|
array_equivalent,
|
||
|
isna,
|
||
|
isnull,
|
||
|
na_value_for_dtype,
|
||
|
notna,
|
||
|
notnull,
|
||
|
)
|
||
|
|
||
|
import pandas as pd
|
||
|
from pandas import DatetimeIndex, Float64Index, NaT, Series, TimedeltaIndex, date_range
|
||
|
import pandas._testing as tm
|
||
|
|
||
|
now = pd.Timestamp.now()
|
||
|
utcnow = pd.Timestamp.now("UTC")
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize("notna_f", [notna, notnull])
|
||
|
def test_notna_notnull(notna_f):
|
||
|
assert notna_f(1.0)
|
||
|
assert not notna_f(None)
|
||
|
assert not notna_f(np.NaN)
|
||
|
|
||
|
with cf.option_context("mode.use_inf_as_na", False):
|
||
|
assert notna_f(np.inf)
|
||
|
assert notna_f(-np.inf)
|
||
|
|
||
|
arr = np.array([1.5, np.inf, 3.5, -np.inf])
|
||
|
result = notna_f(arr)
|
||
|
assert result.all()
|
||
|
|
||
|
with cf.option_context("mode.use_inf_as_na", True):
|
||
|
assert not notna_f(np.inf)
|
||
|
assert not notna_f(-np.inf)
|
||
|
|
||
|
arr = np.array([1.5, np.inf, 3.5, -np.inf])
|
||
|
result = notna_f(arr)
|
||
|
assert result.sum() == 2
|
||
|
|
||
|
with cf.option_context("mode.use_inf_as_na", False):
|
||
|
for s in [
|
||
|
tm.makeFloatSeries(),
|
||
|
tm.makeStringSeries(),
|
||
|
tm.makeObjectSeries(),
|
||
|
tm.makeTimeSeries(),
|
||
|
tm.makePeriodSeries(),
|
||
|
]:
|
||
|
assert isinstance(notna_f(s), Series)
|
||
|
|
||
|
|
||
|
class TestIsNA:
|
||
|
def test_0d_array(self):
|
||
|
assert isna(np.array(np.nan))
|
||
|
assert not isna(np.array(0.0))
|
||
|
assert not isna(np.array(0))
|
||
|
# test object dtype
|
||
|
assert isna(np.array(np.nan, dtype=object))
|
||
|
assert not isna(np.array(0.0, dtype=object))
|
||
|
assert not isna(np.array(0, dtype=object))
|
||
|
|
||
|
def test_empty_object(self):
|
||
|
|
||
|
for shape in [(4, 0), (4,)]:
|
||
|
arr = np.empty(shape=shape, dtype=object)
|
||
|
result = isna(arr)
|
||
|
expected = np.ones(shape=shape, dtype=bool)
|
||
|
tm.assert_numpy_array_equal(result, expected)
|
||
|
|
||
|
@pytest.mark.parametrize("isna_f", [isna, isnull])
|
||
|
def test_isna_isnull(self, isna_f):
|
||
|
assert not isna_f(1.0)
|
||
|
assert isna_f(None)
|
||
|
assert isna_f(np.NaN)
|
||
|
assert float("nan")
|
||
|
assert not isna_f(np.inf)
|
||
|
assert not isna_f(-np.inf)
|
||
|
|
||
|
# type
|
||
|
assert not isna_f(type(Series(dtype=object)))
|
||
|
assert not isna_f(type(Series(dtype=np.float64)))
|
||
|
assert not isna_f(type(pd.DataFrame()))
|
||
|
|
||
|
# series
|
||
|
for s in [
|
||
|
tm.makeFloatSeries(),
|
||
|
tm.makeStringSeries(),
|
||
|
tm.makeObjectSeries(),
|
||
|
tm.makeTimeSeries(),
|
||
|
tm.makePeriodSeries(),
|
||
|
]:
|
||
|
assert isinstance(isna_f(s), Series)
|
||
|
|
||
|
# frame
|
||
|
for df in [
|
||
|
tm.makeTimeDataFrame(),
|
||
|
tm.makePeriodFrame(),
|
||
|
tm.makeMixedDataFrame(),
|
||
|
]:
|
||
|
result = isna_f(df)
|
||
|
expected = df.apply(isna_f)
|
||
|
tm.assert_frame_equal(result, expected)
|
||
|
|
||
|
def test_isna_lists(self):
|
||
|
result = isna([[False]])
|
||
|
exp = np.array([[False]])
|
||
|
tm.assert_numpy_array_equal(result, exp)
|
||
|
|
||
|
result = isna([[1], [2]])
|
||
|
exp = np.array([[False], [False]])
|
||
|
tm.assert_numpy_array_equal(result, exp)
|
||
|
|
||
|
# list of strings / unicode
|
||
|
result = isna(["foo", "bar"])
|
||
|
exp = np.array([False, False])
|
||
|
tm.assert_numpy_array_equal(result, exp)
|
||
|
|
||
|
result = isna(["foo", "bar"])
|
||
|
exp = np.array([False, False])
|
||
|
tm.assert_numpy_array_equal(result, exp)
|
||
|
|
||
|
# GH20675
|
||
|
result = isna([np.NaN, "world"])
|
||
|
exp = np.array([True, False])
|
||
|
tm.assert_numpy_array_equal(result, exp)
|
||
|
|
||
|
def test_isna_nat(self):
|
||
|
result = isna([NaT])
|
||
|
exp = np.array([True])
|
||
|
tm.assert_numpy_array_equal(result, exp)
|
||
|
|
||
|
result = isna(np.array([NaT], dtype=object))
|
||
|
exp = np.array([True])
|
||
|
tm.assert_numpy_array_equal(result, exp)
|
||
|
|
||
|
def test_isna_numpy_nat(self):
|
||
|
arr = np.array(
|
||
|
[
|
||
|
NaT,
|
||
|
np.datetime64("NaT"),
|
||
|
np.timedelta64("NaT"),
|
||
|
np.datetime64("NaT", "s"),
|
||
|
]
|
||
|
)
|
||
|
result = isna(arr)
|
||
|
expected = np.array([True] * 4)
|
||
|
tm.assert_numpy_array_equal(result, expected)
|
||
|
|
||
|
def test_isna_datetime(self):
|
||
|
assert not isna(datetime.now())
|
||
|
assert notna(datetime.now())
|
||
|
|
||
|
idx = date_range("1/1/1990", periods=20)
|
||
|
exp = np.ones(len(idx), dtype=bool)
|
||
|
tm.assert_numpy_array_equal(notna(idx), exp)
|
||
|
|
||
|
idx = np.asarray(idx)
|
||
|
idx[0] = iNaT
|
||
|
idx = DatetimeIndex(idx)
|
||
|
mask = isna(idx)
|
||
|
assert mask[0]
|
||
|
exp = np.array([True] + [False] * (len(idx) - 1), dtype=bool)
|
||
|
tm.assert_numpy_array_equal(mask, exp)
|
||
|
|
||
|
# GH 9129
|
||
|
pidx = idx.to_period(freq="M")
|
||
|
mask = isna(pidx)
|
||
|
assert mask[0]
|
||
|
exp = np.array([True] + [False] * (len(idx) - 1), dtype=bool)
|
||
|
tm.assert_numpy_array_equal(mask, exp)
|
||
|
|
||
|
mask = isna(pidx[1:])
|
||
|
exp = np.zeros(len(mask), dtype=bool)
|
||
|
tm.assert_numpy_array_equal(mask, exp)
|
||
|
|
||
|
def test_isna_old_datetimelike(self):
|
||
|
# isna_old should work for dt64tz, td64, and period, not just tznaive
|
||
|
dti = pd.date_range("2016-01-01", periods=3)
|
||
|
dta = dti._data
|
||
|
dta[-1] = pd.NaT
|
||
|
expected = np.array([False, False, True], dtype=bool)
|
||
|
|
||
|
objs = [dta, dta.tz_localize("US/Eastern"), dta - dta, dta.to_period("D")]
|
||
|
|
||
|
for obj in objs:
|
||
|
with cf.option_context("mode.use_inf_as_na", True):
|
||
|
result = pd.isna(obj)
|
||
|
|
||
|
tm.assert_numpy_array_equal(result, expected)
|
||
|
|
||
|
@pytest.mark.parametrize(
|
||
|
"value, expected",
|
||
|
[
|
||
|
(np.complex128(np.nan), True),
|
||
|
(np.float64(1), False),
|
||
|
(np.array([1, 1 + 0j, np.nan, 3]), np.array([False, False, True, False])),
|
||
|
(
|
||
|
np.array([1, 1 + 0j, np.nan, 3], dtype=object),
|
||
|
np.array([False, False, True, False]),
|
||
|
),
|
||
|
(
|
||
|
np.array([1, 1 + 0j, np.nan, 3]).astype(object),
|
||
|
np.array([False, False, True, False]),
|
||
|
),
|
||
|
],
|
||
|
)
|
||
|
def test_complex(self, value, expected):
|
||
|
result = isna(value)
|
||
|
if is_scalar(result):
|
||
|
assert result is expected
|
||
|
else:
|
||
|
tm.assert_numpy_array_equal(result, expected)
|
||
|
|
||
|
def test_datetime_other_units(self):
|
||
|
idx = DatetimeIndex(["2011-01-01", "NaT", "2011-01-02"])
|
||
|
exp = np.array([False, True, False])
|
||
|
tm.assert_numpy_array_equal(isna(idx), exp)
|
||
|
tm.assert_numpy_array_equal(notna(idx), ~exp)
|
||
|
tm.assert_numpy_array_equal(isna(idx.values), exp)
|
||
|
tm.assert_numpy_array_equal(notna(idx.values), ~exp)
|
||
|
|
||
|
for dtype in [
|
||
|
"datetime64[D]",
|
||
|
"datetime64[h]",
|
||
|
"datetime64[m]",
|
||
|
"datetime64[s]",
|
||
|
"datetime64[ms]",
|
||
|
"datetime64[us]",
|
||
|
"datetime64[ns]",
|
||
|
]:
|
||
|
values = idx.values.astype(dtype)
|
||
|
|
||
|
exp = np.array([False, True, False])
|
||
|
tm.assert_numpy_array_equal(isna(values), exp)
|
||
|
tm.assert_numpy_array_equal(notna(values), ~exp)
|
||
|
|
||
|
exp = Series([False, True, False])
|
||
|
s = Series(values)
|
||
|
tm.assert_series_equal(isna(s), exp)
|
||
|
tm.assert_series_equal(notna(s), ~exp)
|
||
|
s = Series(values, dtype=object)
|
||
|
tm.assert_series_equal(isna(s), exp)
|
||
|
tm.assert_series_equal(notna(s), ~exp)
|
||
|
|
||
|
def test_timedelta_other_units(self):
|
||
|
idx = TimedeltaIndex(["1 days", "NaT", "2 days"])
|
||
|
exp = np.array([False, True, False])
|
||
|
tm.assert_numpy_array_equal(isna(idx), exp)
|
||
|
tm.assert_numpy_array_equal(notna(idx), ~exp)
|
||
|
tm.assert_numpy_array_equal(isna(idx.values), exp)
|
||
|
tm.assert_numpy_array_equal(notna(idx.values), ~exp)
|
||
|
|
||
|
for dtype in [
|
||
|
"timedelta64[D]",
|
||
|
"timedelta64[h]",
|
||
|
"timedelta64[m]",
|
||
|
"timedelta64[s]",
|
||
|
"timedelta64[ms]",
|
||
|
"timedelta64[us]",
|
||
|
"timedelta64[ns]",
|
||
|
]:
|
||
|
values = idx.values.astype(dtype)
|
||
|
|
||
|
exp = np.array([False, True, False])
|
||
|
tm.assert_numpy_array_equal(isna(values), exp)
|
||
|
tm.assert_numpy_array_equal(notna(values), ~exp)
|
||
|
|
||
|
exp = Series([False, True, False])
|
||
|
s = Series(values)
|
||
|
tm.assert_series_equal(isna(s), exp)
|
||
|
tm.assert_series_equal(notna(s), ~exp)
|
||
|
s = Series(values, dtype=object)
|
||
|
tm.assert_series_equal(isna(s), exp)
|
||
|
tm.assert_series_equal(notna(s), ~exp)
|
||
|
|
||
|
def test_period(self):
|
||
|
idx = pd.PeriodIndex(["2011-01", "NaT", "2012-01"], freq="M")
|
||
|
exp = np.array([False, True, False])
|
||
|
tm.assert_numpy_array_equal(isna(idx), exp)
|
||
|
tm.assert_numpy_array_equal(notna(idx), ~exp)
|
||
|
|
||
|
exp = Series([False, True, False])
|
||
|
s = Series(idx)
|
||
|
tm.assert_series_equal(isna(s), exp)
|
||
|
tm.assert_series_equal(notna(s), ~exp)
|
||
|
s = Series(idx, dtype=object)
|
||
|
tm.assert_series_equal(isna(s), exp)
|
||
|
tm.assert_series_equal(notna(s), ~exp)
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize("dtype_equal", [True, False])
|
||
|
def test_array_equivalent(dtype_equal):
|
||
|
assert array_equivalent(
|
||
|
np.array([np.nan, np.nan]), np.array([np.nan, np.nan]), dtype_equal=dtype_equal
|
||
|
)
|
||
|
assert array_equivalent(
|
||
|
np.array([np.nan, 1, np.nan]),
|
||
|
np.array([np.nan, 1, np.nan]),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
assert array_equivalent(
|
||
|
np.array([np.nan, None], dtype="object"),
|
||
|
np.array([np.nan, None], dtype="object"),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
# Check the handling of nested arrays in array_equivalent_object
|
||
|
assert array_equivalent(
|
||
|
np.array([np.array([np.nan, None], dtype="object"), None], dtype="object"),
|
||
|
np.array([np.array([np.nan, None], dtype="object"), None], dtype="object"),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
assert array_equivalent(
|
||
|
np.array([np.nan, 1 + 1j], dtype="complex"),
|
||
|
np.array([np.nan, 1 + 1j], dtype="complex"),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
np.array([np.nan, 1 + 1j], dtype="complex"),
|
||
|
np.array([np.nan, 1 + 2j], dtype="complex"),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
np.array([np.nan, 1, np.nan]),
|
||
|
np.array([np.nan, 2, np.nan]),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
np.array(["a", "b", "c", "d"]), np.array(["e", "e"]), dtype_equal=dtype_equal
|
||
|
)
|
||
|
assert array_equivalent(
|
||
|
Float64Index([0, np.nan]), Float64Index([0, np.nan]), dtype_equal=dtype_equal
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
Float64Index([0, np.nan]), Float64Index([1, np.nan]), dtype_equal=dtype_equal
|
||
|
)
|
||
|
assert array_equivalent(
|
||
|
DatetimeIndex([0, np.nan]), DatetimeIndex([0, np.nan]), dtype_equal=dtype_equal
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
DatetimeIndex([0, np.nan]), DatetimeIndex([1, np.nan]), dtype_equal=dtype_equal
|
||
|
)
|
||
|
assert array_equivalent(
|
||
|
TimedeltaIndex([0, np.nan]),
|
||
|
TimedeltaIndex([0, np.nan]),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
TimedeltaIndex([0, np.nan]),
|
||
|
TimedeltaIndex([1, np.nan]),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
assert array_equivalent(
|
||
|
DatetimeIndex([0, np.nan], tz="US/Eastern"),
|
||
|
DatetimeIndex([0, np.nan], tz="US/Eastern"),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
DatetimeIndex([0, np.nan], tz="US/Eastern"),
|
||
|
DatetimeIndex([1, np.nan], tz="US/Eastern"),
|
||
|
dtype_equal=dtype_equal,
|
||
|
)
|
||
|
# The rest are not dtype_equal
|
||
|
assert not array_equivalent(
|
||
|
DatetimeIndex([0, np.nan]), DatetimeIndex([0, np.nan], tz="US/Eastern")
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
DatetimeIndex([0, np.nan], tz="CET"),
|
||
|
DatetimeIndex([0, np.nan], tz="US/Eastern"),
|
||
|
)
|
||
|
|
||
|
assert not array_equivalent(DatetimeIndex([0, np.nan]), TimedeltaIndex([0, np.nan]))
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize(
|
||
|
"val", [1, 1.1, 1 + 1j, True, "abc", [1, 2], (1, 2), {1, 2}, {"a": 1}, None]
|
||
|
)
|
||
|
def test_array_equivalent_series(val):
|
||
|
arr = np.array([1, 2])
|
||
|
cm = (
|
||
|
tm.assert_produces_warning(FutureWarning, check_stacklevel=False)
|
||
|
if isinstance(val, str)
|
||
|
else nullcontext()
|
||
|
)
|
||
|
with cm:
|
||
|
assert not array_equivalent(Series([arr, arr]), Series([arr, val]))
|
||
|
|
||
|
|
||
|
def test_array_equivalent_different_dtype_but_equal():
|
||
|
# Unclear if this is exposed anywhere in the public-facing API
|
||
|
assert array_equivalent(np.array([1, 2]), np.array([1.0, 2.0]))
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize(
|
||
|
"lvalue, rvalue",
|
||
|
[
|
||
|
# There are 3 variants for each of lvalue and rvalue. We include all
|
||
|
# three for the tz-naive `now` and exclude the datetim64 variant
|
||
|
# for utcnow because it drops tzinfo.
|
||
|
(now, utcnow),
|
||
|
(now.to_datetime64(), utcnow),
|
||
|
(now.to_pydatetime(), utcnow),
|
||
|
(now, utcnow),
|
||
|
(now.to_datetime64(), utcnow.to_pydatetime()),
|
||
|
(now.to_pydatetime(), utcnow.to_pydatetime()),
|
||
|
],
|
||
|
)
|
||
|
def test_array_equivalent_tzawareness(lvalue, rvalue):
|
||
|
# we shouldn't raise if comparing tzaware and tznaive datetimes
|
||
|
left = np.array([lvalue], dtype=object)
|
||
|
right = np.array([rvalue], dtype=object)
|
||
|
|
||
|
assert not array_equivalent(left, right, strict_nan=True)
|
||
|
assert not array_equivalent(left, right, strict_nan=False)
|
||
|
|
||
|
|
||
|
def test_array_equivalent_compat():
|
||
|
# see gh-13388
|
||
|
m = np.array([(1, 2), (3, 4)], dtype=[("a", int), ("b", float)])
|
||
|
n = np.array([(1, 2), (3, 4)], dtype=[("a", int), ("b", float)])
|
||
|
assert array_equivalent(m, n, strict_nan=True)
|
||
|
assert array_equivalent(m, n, strict_nan=False)
|
||
|
|
||
|
m = np.array([(1, 2), (3, 4)], dtype=[("a", int), ("b", float)])
|
||
|
n = np.array([(1, 2), (4, 3)], dtype=[("a", int), ("b", float)])
|
||
|
assert not array_equivalent(m, n, strict_nan=True)
|
||
|
assert not array_equivalent(m, n, strict_nan=False)
|
||
|
|
||
|
m = np.array([(1, 2), (3, 4)], dtype=[("a", int), ("b", float)])
|
||
|
n = np.array([(1, 2), (3, 4)], dtype=[("b", int), ("a", float)])
|
||
|
assert not array_equivalent(m, n, strict_nan=True)
|
||
|
assert not array_equivalent(m, n, strict_nan=False)
|
||
|
|
||
|
|
||
|
def test_array_equivalent_str():
|
||
|
for dtype in ["O", "S", "U"]:
|
||
|
assert array_equivalent(
|
||
|
np.array(["A", "B"], dtype=dtype), np.array(["A", "B"], dtype=dtype)
|
||
|
)
|
||
|
assert not array_equivalent(
|
||
|
np.array(["A", "B"], dtype=dtype), np.array(["A", "X"], dtype=dtype)
|
||
|
)
|
||
|
|
||
|
|
||
|
def test_array_equivalent_nested():
|
||
|
# reached in groupby aggregations, make sure we use np.any when checking
|
||
|
# if the comparison is truthy
|
||
|
left = np.array([np.array([50, 70, 90]), np.array([20, 30, 40])], dtype=object)
|
||
|
right = np.array([np.array([50, 70, 90]), np.array([20, 30, 40])], dtype=object)
|
||
|
|
||
|
assert array_equivalent(left, right, strict_nan=True)
|
||
|
assert not array_equivalent(left, right[::-1], strict_nan=True)
|
||
|
|
||
|
left = np.array([np.array([50, 50, 50]), np.array([40, 40, 40])], dtype=object)
|
||
|
right = np.array([50, 40])
|
||
|
assert not array_equivalent(left, right, strict_nan=True)
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize(
|
||
|
"dtype, na_value",
|
||
|
[
|
||
|
# Datetime-like
|
||
|
(np.dtype("M8[ns]"), NaT),
|
||
|
(np.dtype("m8[ns]"), NaT),
|
||
|
(DatetimeTZDtype.construct_from_string("datetime64[ns, US/Eastern]"), NaT),
|
||
|
(PeriodDtype("M"), NaT),
|
||
|
# Integer
|
||
|
("u1", 0),
|
||
|
("u2", 0),
|
||
|
("u4", 0),
|
||
|
("u8", 0),
|
||
|
("i1", 0),
|
||
|
("i2", 0),
|
||
|
("i4", 0),
|
||
|
("i8", 0),
|
||
|
# Bool
|
||
|
("bool", False),
|
||
|
# Float
|
||
|
("f2", np.nan),
|
||
|
("f4", np.nan),
|
||
|
("f8", np.nan),
|
||
|
# Object
|
||
|
("O", np.nan),
|
||
|
# Interval
|
||
|
(IntervalDtype(), np.nan),
|
||
|
],
|
||
|
)
|
||
|
def test_na_value_for_dtype(dtype, na_value):
|
||
|
result = na_value_for_dtype(dtype)
|
||
|
assert result is na_value
|
||
|
|
||
|
|
||
|
class TestNAObj:
|
||
|
|
||
|
_1d_methods = ["isnaobj", "isnaobj_old"]
|
||
|
_2d_methods = ["isnaobj2d", "isnaobj2d_old"]
|
||
|
|
||
|
def _check_behavior(self, arr, expected):
|
||
|
for method in TestNAObj._1d_methods:
|
||
|
result = getattr(libmissing, method)(arr)
|
||
|
tm.assert_numpy_array_equal(result, expected)
|
||
|
|
||
|
arr = np.atleast_2d(arr)
|
||
|
expected = np.atleast_2d(expected)
|
||
|
|
||
|
for method in TestNAObj._2d_methods:
|
||
|
result = getattr(libmissing, method)(arr)
|
||
|
tm.assert_numpy_array_equal(result, expected)
|
||
|
|
||
|
def test_basic(self):
|
||
|
arr = np.array([1, None, "foo", -5.1, pd.NaT, np.nan])
|
||
|
expected = np.array([False, True, False, False, True, True])
|
||
|
|
||
|
self._check_behavior(arr, expected)
|
||
|
|
||
|
def test_non_obj_dtype(self):
|
||
|
arr = np.array([1, 3, np.nan, 5], dtype=float)
|
||
|
expected = np.array([False, False, True, False])
|
||
|
|
||
|
self._check_behavior(arr, expected)
|
||
|
|
||
|
def test_empty_arr(self):
|
||
|
arr = np.array([])
|
||
|
expected = np.array([], dtype=bool)
|
||
|
|
||
|
self._check_behavior(arr, expected)
|
||
|
|
||
|
def test_empty_str_inp(self):
|
||
|
arr = np.array([""]) # empty but not na
|
||
|
expected = np.array([False])
|
||
|
|
||
|
self._check_behavior(arr, expected)
|
||
|
|
||
|
def test_empty_like(self):
|
||
|
# see gh-13717: no segfaults!
|
||
|
arr = np.empty_like([None])
|
||
|
expected = np.array([True])
|
||
|
|
||
|
self._check_behavior(arr, expected)
|
||
|
|
||
|
|
||
|
m8_units = ["as", "ps", "ns", "us", "ms", "s", "m", "h", "D", "W", "M", "Y"]
|
||
|
|
||
|
na_vals = (
|
||
|
[
|
||
|
None,
|
||
|
NaT,
|
||
|
float("NaN"),
|
||
|
complex("NaN"),
|
||
|
np.nan,
|
||
|
np.float64("NaN"),
|
||
|
np.float32("NaN"),
|
||
|
np.complex64(np.nan),
|
||
|
np.complex128(np.nan),
|
||
|
np.datetime64("NaT"),
|
||
|
np.timedelta64("NaT"),
|
||
|
]
|
||
|
+ [np.datetime64("NaT", unit) for unit in m8_units]
|
||
|
+ [np.timedelta64("NaT", unit) for unit in m8_units]
|
||
|
)
|
||
|
|
||
|
inf_vals = [
|
||
|
float("inf"),
|
||
|
float("-inf"),
|
||
|
complex("inf"),
|
||
|
complex("-inf"),
|
||
|
np.inf,
|
||
|
np.NINF,
|
||
|
]
|
||
|
|
||
|
int_na_vals = [
|
||
|
# Values that match iNaT, which we treat as null in specific cases
|
||
|
np.int64(NaT.value),
|
||
|
int(NaT.value),
|
||
|
]
|
||
|
|
||
|
sometimes_na_vals = [Decimal("NaN")]
|
||
|
|
||
|
never_na_vals = [
|
||
|
# float/complex values that when viewed as int64 match iNaT
|
||
|
-0.0,
|
||
|
np.float64("-0.0"),
|
||
|
-0j,
|
||
|
np.complex64(-0j),
|
||
|
]
|
||
|
|
||
|
|
||
|
class TestLibMissing:
|
||
|
def test_checknull(self):
|
||
|
for value in na_vals:
|
||
|
assert libmissing.checknull(value)
|
||
|
|
||
|
for value in inf_vals:
|
||
|
assert not libmissing.checknull(value)
|
||
|
|
||
|
for value in int_na_vals:
|
||
|
assert not libmissing.checknull(value)
|
||
|
|
||
|
for value in sometimes_na_vals:
|
||
|
assert not libmissing.checknull(value)
|
||
|
|
||
|
for value in never_na_vals:
|
||
|
assert not libmissing.checknull(value)
|
||
|
|
||
|
def test_checknull_old(self):
|
||
|
for value in na_vals:
|
||
|
assert libmissing.checknull_old(value)
|
||
|
|
||
|
for value in inf_vals:
|
||
|
assert libmissing.checknull_old(value)
|
||
|
|
||
|
for value in int_na_vals:
|
||
|
assert not libmissing.checknull_old(value)
|
||
|
|
||
|
for value in sometimes_na_vals:
|
||
|
assert not libmissing.checknull_old(value)
|
||
|
|
||
|
for value in never_na_vals:
|
||
|
assert not libmissing.checknull_old(value)
|
||
|
|
||
|
def test_is_null_datetimelike(self):
|
||
|
for value in na_vals:
|
||
|
assert is_null_datetimelike(value)
|
||
|
assert is_null_datetimelike(value, False)
|
||
|
|
||
|
for value in inf_vals:
|
||
|
assert not is_null_datetimelike(value)
|
||
|
assert not is_null_datetimelike(value, False)
|
||
|
|
||
|
for value in int_na_vals:
|
||
|
assert is_null_datetimelike(value)
|
||
|
assert not is_null_datetimelike(value, False)
|
||
|
|
||
|
for value in sometimes_na_vals:
|
||
|
assert not is_null_datetimelike(value)
|
||
|
assert not is_null_datetimelike(value, False)
|
||
|
|
||
|
for value in never_na_vals:
|
||
|
assert not is_null_datetimelike(value)
|