Skip to content

Commit 810fe4f

Browse files
authored
CLN: Stopped casting values in Series/Index.isin for datelike dtypes (#58645)
* CLN: Stopped casting values in Series/Index.isin for datelike dtypes * Support mixed case * Avoid infer_objects
1 parent 51f891e commit 810fe4f

File tree

3 files changed

+11
-42
lines changed

3 files changed

+11
-42
lines changed

doc/source/whatsnew/v3.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ Removal of prior version deprecations/changes
247247
- Removed the "closed" and "normalize" keywords in :meth:`DatetimeIndex.__new__` (:issue:`52628`)
248248
- Removed the deprecated ``delim_whitespace`` keyword in :func:`read_csv` and :func:`read_table`, use ``sep=r"\s+"`` instead (:issue:`55569`)
249249
- Require :meth:`SparseDtype.fill_value` to be a valid value for the :meth:`SparseDtype.subtype` (:issue:`53043`)
250+
- Stopped automatically casting non-datetimelike values (mainly strings) in :meth:`Series.isin` and :meth:`Index.isin` with ``datetime64``, ``timedelta64``, and :class:`PeriodDtype` dtypes (:issue:`53111`)
250251
- Stopped performing dtype inference when setting a :class:`Index` into a :class:`DataFrame` (:issue:`56102`)
251252
- Stopped performing dtype inference with in :meth:`Index.insert` with object-dtype index; this often affects the index/columns that result when setting new entries into an empty :class:`Series` or :class:`DataFrame` (:issue:`51363`)
252253
- Removed the "closed" and "unit" keywords in :meth:`TimedeltaIndex.__new__` (:issue:`52628`, :issue:`55499`)

pandas/core/arrays/datetimelike.py

+5-34
Original file line numberDiff line numberDiff line change
@@ -759,14 +759,6 @@ def isin(self, values: ArrayLike) -> npt.NDArray[np.bool_]:
759759
values = ensure_wrapped_if_datetimelike(values)
760760

761761
if not isinstance(values, type(self)):
762-
inferable = [
763-
"timedelta",
764-
"timedelta64",
765-
"datetime",
766-
"datetime64",
767-
"date",
768-
"period",
769-
]
770762
if values.dtype == object:
771763
values = lib.maybe_convert_objects(
772764
values, # type: ignore[arg-type]
@@ -775,32 +767,11 @@ def isin(self, values: ArrayLike) -> npt.NDArray[np.bool_]:
775767
)
776768
if values.dtype != object:
777769
return self.isin(values)
778-
779-
inferred = lib.infer_dtype(values, skipna=False)
780-
if inferred not in inferable:
781-
if inferred == "string":
782-
pass
783-
784-
elif "mixed" in inferred:
785-
return isin(self.astype(object), values)
786-
else:
787-
return np.zeros(self.shape, dtype=bool)
788-
789-
try:
790-
values = type(self)._from_sequence(values)
791-
except ValueError:
792-
return isin(self.astype(object), values)
793-
else:
794-
warnings.warn(
795-
# GH#53111
796-
f"The behavior of 'isin' with dtype={self.dtype} and "
797-
"castable values (e.g. strings) is deprecated. In a "
798-
"future version, these will not be considered matching "
799-
"by isin. Explicitly cast to the appropriate dtype before "
800-
"calling isin instead.",
801-
FutureWarning,
802-
stacklevel=find_stack_level(),
803-
)
770+
else:
771+
# TODO: Deprecate this case
772+
# https://github.com/pandas-dev/pandas/pull/58645/files#r1604055791
773+
return isin(self.astype(object), values)
774+
return np.zeros(self.shape, dtype=bool)
804775

805776
if self.dtype.kind in "mM":
806777
self = cast("DatetimeArray | TimedeltaArray", self)

pandas/tests/test_algos.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -990,21 +990,18 @@ def test_isin_datetimelike_all_nat(self, dtype):
990990
tm.assert_numpy_array_equal(result, expected)
991991

992992
@pytest.mark.parametrize("dtype", ["m8[ns]", "M8[ns]", "M8[ns, UTC]"])
993-
def test_isin_datetimelike_strings_deprecated(self, dtype):
993+
def test_isin_datetimelike_strings_returns_false(self, dtype):
994994
# GH#53111
995995
dta = date_range("2013-01-01", periods=3)._values
996996
arr = Series(dta.view("i8")).array.view(dtype)
997997

998998
vals = [str(x) for x in arr]
999-
msg = "The behavior of 'isin' with dtype=.* is deprecated"
1000-
with tm.assert_produces_warning(FutureWarning, match=msg):
1001-
res = algos.isin(arr, vals)
1002-
assert res.all()
999+
res = algos.isin(arr, vals)
1000+
assert not res.any()
10031001

10041002
vals2 = np.array(vals, dtype=str)
1005-
with tm.assert_produces_warning(FutureWarning, match=msg):
1006-
res2 = algos.isin(arr, vals2)
1007-
assert res2.all()
1003+
res2 = algos.isin(arr, vals2)
1004+
assert not res2.any()
10081005

10091006
def test_isin_dt64tz_with_nat(self):
10101007
# the all-NaT values used to get inferred to tznaive, which was evaluated

0 commit comments

Comments
 (0)