Skip to content

Commit 1506ed5

Browse files
authored
DEPR: disallow int fill_value in shift with dt64/td64 (#49362)
1 parent f1bb3b2 commit 1506ed5

File tree

5 files changed

+11
-63
lines changed

5 files changed

+11
-63
lines changed

doc/source/whatsnew/v2.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ Removal of prior version deprecations/changes
243243
- Removed :meth:`Series.str.__iter__` (:issue:`28277`)
244244
- Removed ``pandas.SparseArray`` in favor of :class:`arrays.SparseArray` (:issue:`30642`)
245245
- Removed ``pandas.SparseSeries`` and ``pandas.SparseDataFrame``, including pickle support. (:issue:`30642`)
246+
- Enforced disallowing passing an integer ``fill_value`` to :meth:`DataFrame.shift` and :meth:`Series.shift`` with datetime64, timedelta64, or period dtypes (:issue:`32591`)
246247
- Enforced disallowing a string column label into ``times`` in :meth:`DataFrame.ewm` (:issue:`43265`)
247248
- Enforced disallowing a tuple of column labels into :meth:`.DataFrameGroupBy.__getitem__` (:issue:`30546`)
248249
- Removed setting Categorical._codes directly (:issue:`41429`)

pandas/core/arrays/_mixins.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,11 @@ def _validate_searchsorted_value(
252252
@doc(ExtensionArray.shift)
253253
def shift(self, periods: int = 1, fill_value=None, axis: AxisInt = 0):
254254

255-
fill_value = self._validate_shift_value(fill_value)
255+
fill_value = self._validate_scalar(fill_value)
256256
new_values = shift(self._ndarray, periods, axis, fill_value)
257257

258258
return self._from_backing_data(new_values)
259259

260-
def _validate_shift_value(self, fill_value):
261-
# TODO(2.0): after deprecation in datetimelikearraymixin is enforced,
262-
# we can remove this and use validate_fill_value directly
263-
return self._validate_scalar(fill_value)
264-
265260
def __setitem__(self, key, value) -> None:
266261
key = check_array_indexer(self, key)
267262
value = self._validate_setitem_value(value)

pandas/core/arrays/datetimelike.py

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -603,37 +603,6 @@ def _validate_comparison_value(self, other):
603603

604604
return other
605605

606-
def _validate_shift_value(self, fill_value):
607-
# TODO(2.0): once this deprecation is enforced, use _validate_scalar
608-
if is_valid_na_for_dtype(fill_value, self.dtype):
609-
fill_value = NaT
610-
elif isinstance(fill_value, self._recognized_scalars):
611-
fill_value = self._scalar_type(fill_value)
612-
else:
613-
new_fill: DatetimeLikeScalar
614-
615-
# only warn if we're not going to raise
616-
if self._scalar_type is Period and lib.is_integer(fill_value):
617-
# kludge for #31971 since Period(integer) tries to cast to str
618-
new_fill = Period._from_ordinal(fill_value, freq=self.freq)
619-
else:
620-
new_fill = self._scalar_type(fill_value)
621-
622-
# stacklevel here is chosen to be correct when called from
623-
# DataFrame.shift or Series.shift
624-
warnings.warn(
625-
f"Passing {type(fill_value)} to shift is deprecated and "
626-
"will raise in a future version, pass "
627-
f"{self._scalar_type.__name__} instead.",
628-
FutureWarning,
629-
# There is no way to hard-code the level since this might be
630-
# reached directly or called from the Index or Block method
631-
stacklevel=find_stack_level(),
632-
)
633-
fill_value = new_fill
634-
635-
return self._unbox(fill_value, setitem=True)
636-
637606
def _validate_scalar(
638607
self,
639608
value,

pandas/tests/arrays/test_datetimelike.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -554,22 +554,12 @@ def test_inplace_arithmetic(self):
554554
tm.assert_equal(arr, expected)
555555

556556
def test_shift_fill_int_deprecated(self):
557-
# GH#31971
557+
# GH#31971, enforced in 2.0
558558
data = np.arange(10, dtype="i8") * 24 * 3600 * 10**9
559559
arr = self.array_cls(data, freq="D")
560560

561-
msg = "Passing <class 'int'> to shift"
562-
with tm.assert_produces_warning(FutureWarning, match=msg):
563-
result = arr.shift(1, fill_value=1)
564-
565-
expected = arr.copy()
566-
if self.array_cls is PeriodArray:
567-
fill_val = arr._scalar_type._from_ordinal(1, freq=arr.freq)
568-
else:
569-
fill_val = arr._scalar_type(1)
570-
expected[0] = fill_val
571-
expected[1:] = arr[:-1]
572-
tm.assert_equal(result, expected)
561+
with pytest.raises(TypeError, match="value should be a"):
562+
arr.shift(1, fill_value=1)
573563

574564
def test_median(self, arr1d):
575565
arr = arr1d

pandas/tests/frame/methods/test_shift.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -505,26 +505,19 @@ def test_shift_dt64values_int_fill_deprecated(self):
505505
# GH#31971
506506
ser = Series([pd.Timestamp("2020-01-01"), pd.Timestamp("2020-01-02")])
507507

508-
with tm.assert_produces_warning(FutureWarning):
509-
result = ser.shift(1, fill_value=0)
510-
expected = Series([pd.Timestamp(0), ser[0]])
511-
tm.assert_series_equal(result, expected)
508+
with pytest.raises(TypeError, match="value should be a"):
509+
ser.shift(1, fill_value=0)
512510

513511
df = ser.to_frame()
514-
with tm.assert_produces_warning(FutureWarning):
515-
result = df.shift(1, fill_value=0)
516-
expected = expected.to_frame()
517-
tm.assert_frame_equal(result, expected)
512+
with pytest.raises(TypeError, match="value should be a"):
513+
df.shift(1, fill_value=0)
518514

519515
# axis = 1
520516
df2 = DataFrame({"A": ser, "B": ser})
521517
df2._consolidate_inplace()
522518

523-
with tm.assert_produces_warning(FutureWarning):
524-
result = df2.shift(1, axis=1, fill_value=0)
525-
526-
expected = DataFrame({"A": [pd.Timestamp(0), pd.Timestamp(0)], "B": df2["A"]})
527-
tm.assert_frame_equal(result, expected)
519+
with pytest.raises(TypeError, match="value should be a"):
520+
df2.shift(1, axis=1, fill_value=0)
528521

529522
# same thing but not consolidated
530523
# This isn't great that we get different behavior, but

0 commit comments

Comments
 (0)