From 9c40a045516e01c03f2115a1f2cedfd4a17f6ad7 Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 16 Dec 2021 19:23:23 -0800 Subject: [PATCH 1/7] TST/REF: share shift tests --- pandas/tests/frame/methods/test_shift.py | 144 +++++++++++++-------- pandas/tests/series/methods/test_shift.py | 145 +--------------------- 2 files changed, 94 insertions(+), 195 deletions(-) diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index 9cd0b8bb5b315..c45b68eee35bc 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -15,8 +15,14 @@ import pandas._testing as tm +def get_obj(df, klass): + if klass is Series: + return df._ixs(0, axis=1) + return df + + class TestDataFrameShift: - def test_shift(self, datetime_frame, int_frame): + def test_shift(self, datetime_frame, frame_or_series): # naive shift shiftedFrame = datetime_frame.shift(5) tm.assert_index_equal(shiftedFrame.index, datetime_frame.index) @@ -47,28 +53,39 @@ def test_shift(self, datetime_frame, int_frame): datetime_frame.xs(d), shiftedFrame.xs(shifted_d), check_names=False ) - # shift int frame - int_shifted = int_frame.shift(1) # noqa - + def test_shift_with_periodindex(self, frame_or_series): # Shifting with PeriodIndex ps = tm.makePeriodFrame() + ps = get_obj(ps, frame_or_series) + shifted = ps.shift(1) unshifted = shifted.shift(-1) tm.assert_index_equal(shifted.index, ps.index) tm.assert_index_equal(unshifted.index, ps.index) - tm.assert_numpy_array_equal( - unshifted.iloc[:, 0].dropna().values, ps.iloc[:-1, 0].values - ) + if frame_or_series is DataFrame: + tm.assert_numpy_array_equal( + unshifted.iloc[:, 0].dropna().values, ps.iloc[:-1, 0].values + ) + else: + tm.assert_numpy_array_equal(unshifted.dropna().values, ps.values[:-1]) shifted2 = ps.shift(1, "B") shifted3 = ps.shift(1, offsets.BDay()) - tm.assert_frame_equal(shifted2, shifted3) - tm.assert_frame_equal(ps, shifted2.shift(-1, "B")) + tm.assert_equal(shifted2, shifted3) + tm.assert_equal(ps, shifted2.shift(-1, "B")) msg = "does not match PeriodIndex freq" with pytest.raises(ValueError, match=msg): ps.shift(freq="D") + # legacy support + shifted4 = ps.shift(1, freq="B") + tm.assert_equal(shifted2, shifted4) + + shifted5 = ps.shift(1, freq=offsets.BDay()) + tm.assert_equal(shifted5, shifted4) + + def test_shift_other_axis(self): # shift other axis # GH#6371 df = DataFrame(np.random.rand(10, 5)) @@ -80,6 +97,7 @@ def test_shift(self, datetime_frame, int_frame): result = df.shift(1, axis=1) tm.assert_frame_equal(result, expected) + def test_shift_named_axis(self): # shift named axis df = DataFrame(np.random.rand(10, 5)) expected = pd.concat( @@ -108,22 +126,33 @@ def test_shift_categorical(self): xp = DataFrame({"one": s1.shift(1), "two": s2.shift(1)}) tm.assert_frame_equal(rs, xp) - def test_shift_fill_value(self): + def test_shift_fill_value(self, frame_or_series): # GH#24128 - df = DataFrame( - [1, 2, 3, 4, 5], index=date_range("1/1/2000", periods=5, freq="H") - ) - exp = DataFrame( - [0, 1, 2, 3, 4], index=date_range("1/1/2000", periods=5, freq="H") - ) - result = df.shift(1, fill_value=0) - tm.assert_frame_equal(result, exp) + dti = date_range("1/1/2000", periods=5, freq="H") - exp = DataFrame( - [0, 0, 1, 2, 3], index=date_range("1/1/2000", periods=5, freq="H") - ) - result = df.shift(2, fill_value=0) - tm.assert_frame_equal(result, exp) + ts = frame_or_series([1.0, 2.0, 3.0, 4.0, 5.0], index=dti) + exp = frame_or_series([0.0, 1.0, 2.0, 3.0, 4.0], index=dti) + # check that fill value works + result = ts.shift(1, fill_value=0.0) + tm.assert_equal(result, exp) + + exp = frame_or_series([0.0, 0.0, 1.0, 2.0, 3.0], index=dti) + result = ts.shift(2, fill_value=0.0) + tm.assert_equal(result, exp) + + ts = frame_or_series([1, 2, 3]) + res = ts.shift(2, fill_value=0) + assert tm.get_dtype(res) == tm.get_dtype(ts) + + # retain integer dtype + obj = frame_or_series([1, 2, 3, 4, 5], index=dti) + exp = frame_or_series([0, 1, 2, 3, 4], index=dti) + result = obj.shift(1, fill_value=0) + tm.assert_equal(result, exp) + + exp = frame_or_series([0, 0, 1, 2, 3], index=dti) + result = obj.shift(2, fill_value=0) + tm.assert_equal(result, exp) def test_shift_empty(self): # Regression test for GH#8019 @@ -210,101 +239,112 @@ def test_shift_axis1_multiple_blocks_with_int_fill(self): tm.assert_frame_equal(result, expected) @pytest.mark.filterwarnings("ignore:tshift is deprecated:FutureWarning") - def test_tshift(self, datetime_frame): + def test_tshift(self, datetime_frame, frame_or_series): # TODO(2.0): remove this test when tshift deprecation is enforced # PeriodIndex ps = tm.makePeriodFrame() + ps = get_obj(ps, frame_or_series) shifted = ps.tshift(1) unshifted = shifted.tshift(-1) - tm.assert_frame_equal(unshifted, ps) + tm.assert_equal(unshifted, ps) shifted2 = ps.tshift(freq="B") - tm.assert_frame_equal(shifted, shifted2) + tm.assert_equal(shifted, shifted2) shifted3 = ps.tshift(freq=offsets.BDay()) - tm.assert_frame_equal(shifted, shifted3) + tm.assert_equal(shifted, shifted3) msg = "Given freq M does not match PeriodIndex freq B" with pytest.raises(ValueError, match=msg): ps.tshift(freq="M") # DatetimeIndex - shifted = datetime_frame.tshift(1) + dtobj = get_obj(datetime_frame, frame_or_series) + shifted = dtobj.tshift(1) unshifted = shifted.tshift(-1) - tm.assert_frame_equal(datetime_frame, unshifted) + tm.assert_equal(dtobj, unshifted) - shifted2 = datetime_frame.tshift(freq=datetime_frame.index.freq) - tm.assert_frame_equal(shifted, shifted2) + shifted2 = dtobj.tshift(freq=dtobj.index.freq) + tm.assert_equal(shifted, shifted2) inferred_ts = DataFrame( datetime_frame.values, Index(np.asarray(datetime_frame.index)), columns=datetime_frame.columns, ) + inferred_ts = get_obj(inferred_ts, frame_or_series) shifted = inferred_ts.tshift(1) - expected = datetime_frame.tshift(1) + expected = dtobj.tshift(1) expected.index = expected.index._with_freq(None) - tm.assert_frame_equal(shifted, expected) + tm.assert_equal(shifted, expected) unshifted = shifted.tshift(-1) - tm.assert_frame_equal(unshifted, inferred_ts) + tm.assert_equal(unshifted, inferred_ts) - no_freq = datetime_frame.iloc[[0, 5, 7], :] + no_freq = dtobj.iloc[[0, 5, 7]] msg = "Freq was not set in the index hence cannot be inferred" with pytest.raises(ValueError, match=msg): no_freq.tshift() - def test_tshift_deprecated(self, datetime_frame): + def test_tshift_deprecated(self, datetime_frame, frame_or_series): # GH#11631 + dtobj = get_obj(datetime_frame, frame_or_series) with tm.assert_produces_warning(FutureWarning): - datetime_frame.tshift() + dtobj.tshift() - def test_period_index_frame_shift_with_freq(self): + def test_period_index_frame_shift_with_freq(self, frame_or_series): ps = tm.makePeriodFrame() + ps = get_obj(ps, frame_or_series) shifted = ps.shift(1, freq="infer") unshifted = shifted.shift(-1, freq="infer") - tm.assert_frame_equal(unshifted, ps) + tm.assert_equal(unshifted, ps) shifted2 = ps.shift(freq="B") - tm.assert_frame_equal(shifted, shifted2) + tm.assert_equal(shifted, shifted2) shifted3 = ps.shift(freq=offsets.BDay()) - tm.assert_frame_equal(shifted, shifted3) + tm.assert_equal(shifted, shifted3) - def test_datetime_frame_shift_with_freq(self, datetime_frame): - shifted = datetime_frame.shift(1, freq="infer") + def test_datetime_frame_shift_with_freq(self, datetime_frame, frame_or_series): + dtobj = get_obj(datetime_frame, frame_or_series) + shifted = dtobj.shift(1, freq="infer") unshifted = shifted.shift(-1, freq="infer") - tm.assert_frame_equal(datetime_frame, unshifted) + tm.assert_equal(dtobj, unshifted) - shifted2 = datetime_frame.shift(freq=datetime_frame.index.freq) - tm.assert_frame_equal(shifted, shifted2) + shifted2 = dtobj.shift(freq=dtobj.index.freq) + tm.assert_equal(shifted, shifted2) inferred_ts = DataFrame( datetime_frame.values, Index(np.asarray(datetime_frame.index)), columns=datetime_frame.columns, ) + inferred_ts = get_obj(inferred_ts, frame_or_series) shifted = inferred_ts.shift(1, freq="infer") - expected = datetime_frame.shift(1, freq="infer") + expected = dtobj.shift(1, freq="infer") expected.index = expected.index._with_freq(None) - tm.assert_frame_equal(shifted, expected) + tm.assert_equal(shifted, expected) unshifted = shifted.shift(-1, freq="infer") - tm.assert_frame_equal(unshifted, inferred_ts) + tm.assert_equal(unshifted, inferred_ts) - def test_period_index_frame_shift_with_freq_error(self): + def test_period_index_frame_shift_with_freq_error(self, frame_or_series): ps = tm.makePeriodFrame() + ps = get_obj(ps, frame_or_series) msg = "Given freq M does not match PeriodIndex freq B" with pytest.raises(ValueError, match=msg): ps.shift(freq="M") - def test_datetime_frame_shift_with_freq_error(self, datetime_frame): - no_freq = datetime_frame.iloc[[0, 5, 7], :] + def test_datetime_frame_shift_with_freq_error( + self, datetime_frame, frame_or_series + ): + dtobj = get_obj(datetime_frame, frame_or_series) + no_freq = dtobj.iloc[[0, 5, 7]] msg = "Freq was not set in the index hence cannot be inferred" with pytest.raises(ValueError, match=msg): no_freq.shift(freq="infer") diff --git a/pandas/tests/series/methods/test_shift.py b/pandas/tests/series/methods/test_shift.py index 4fb378720d89d..f584944690a7e 100644 --- a/pandas/tests/series/methods/test_shift.py +++ b/pandas/tests/series/methods/test_shift.py @@ -6,7 +6,6 @@ import pandas as pd from pandas import ( DatetimeIndex, - Index, NaT, Series, TimedeltaIndex, @@ -66,30 +65,7 @@ def test_shift(self, datetime_series): unshifted = datetime_series.shift(0) tm.assert_series_equal(unshifted, datetime_series) - # Shifting with PeriodIndex - ps = tm.makePeriodSeries() - shifted = ps.shift(1) - unshifted = shifted.shift(-1) - tm.assert_index_equal(shifted.index, ps.index) - tm.assert_index_equal(unshifted.index, ps.index) - tm.assert_numpy_array_equal(unshifted.dropna().values, ps.values[:-1]) - - shifted2 = ps.shift(1, "B") - shifted3 = ps.shift(1, BDay()) - tm.assert_series_equal(shifted2, shifted3) - tm.assert_series_equal(ps, shifted2.shift(-1, "B")) - - msg = "Given freq D does not match PeriodIndex freq B" - with pytest.raises(ValueError, match=msg): - ps.shift(freq="D") - - # legacy support - shifted4 = ps.shift(1, freq="B") - tm.assert_series_equal(shifted2, shifted4) - - shifted5 = ps.shift(1, freq=BDay()) - tm.assert_series_equal(shifted5, shifted4) - + def test_shift_32bit_take(self): # 32-bit taking # GH#8129 index = date_range("2000-01-01", periods=5) @@ -100,6 +76,7 @@ def test_shift(self, datetime_series): expected = Series([np.nan, 0, 1, 2, 3], index=index) tm.assert_series_equal(result, expected) + def test_shift_with_tz(self): # GH#8260 # with tz s = Series( @@ -135,29 +112,6 @@ def test_shift2(self): with pytest.raises(NullFrequencyError, match=msg): idx.shift(1) - def test_shift_fill_value(self): - # GH#24128 - ts = Series( - [1.0, 2.0, 3.0, 4.0, 5.0], index=date_range("1/1/2000", periods=5, freq="H") - ) - - exp = Series( - [0.0, 1.0, 2.0, 3.0, 4.0], index=date_range("1/1/2000", periods=5, freq="H") - ) - # check that fill value works - result = ts.shift(1, fill_value=0.0) - tm.assert_series_equal(result, exp) - - exp = Series( - [0.0, 0.0, 1.0, 2.0, 3.0], index=date_range("1/1/2000", periods=5, freq="H") - ) - result = ts.shift(2, fill_value=0.0) - tm.assert_series_equal(result, exp) - - ts = Series([1, 2, 3]) - res = ts.shift(2, fill_value=0) - assert res.dtype == ts.dtype - def test_shift_categorical_fill_value(self): ts = Series(["a", "b", "c", "d"], dtype="category") res = ts.shift(1, fill_value="a") @@ -200,101 +154,6 @@ def test_shift_dst(self): tm.assert_series_equal(res, exp) assert res.dtype == "datetime64[ns, US/Eastern]" - @pytest.mark.filterwarnings("ignore:tshift is deprecated:FutureWarning") - def test_tshift(self, datetime_series): - # TODO(2.0): remove this test when tshift deprecation is enforced - - # PeriodIndex - ps = tm.makePeriodSeries() - shifted = ps.tshift(1) - unshifted = shifted.tshift(-1) - - tm.assert_series_equal(unshifted, ps) - - shifted2 = ps.tshift(freq="B") - tm.assert_series_equal(shifted, shifted2) - - shifted3 = ps.tshift(freq=BDay()) - tm.assert_series_equal(shifted, shifted3) - - msg = "Given freq M does not match PeriodIndex freq B" - with pytest.raises(ValueError, match=msg): - ps.tshift(freq="M") - - # DatetimeIndex - shifted = datetime_series.tshift(1) - unshifted = shifted.tshift(-1) - - tm.assert_series_equal(datetime_series, unshifted) - - shifted2 = datetime_series.tshift(freq=datetime_series.index.freq) - tm.assert_series_equal(shifted, shifted2) - - inferred_ts = Series( - datetime_series.values, Index(np.asarray(datetime_series.index)), name="ts" - ) - shifted = inferred_ts.tshift(1) - expected = datetime_series.tshift(1) - expected.index = expected.index._with_freq(None) - tm.assert_series_equal(shifted, expected) - - unshifted = shifted.tshift(-1) - tm.assert_series_equal(unshifted, inferred_ts) - - no_freq = datetime_series[[0, 5, 7]] - msg = "Freq was not set in the index hence cannot be inferred" - with pytest.raises(ValueError, match=msg): - no_freq.tshift() - - def test_tshift_deprecated(self, datetime_series): - # GH#11631 - with tm.assert_produces_warning(FutureWarning): - datetime_series.tshift() - - def test_period_index_series_shift_with_freq(self): - ps = tm.makePeriodSeries() - - shifted = ps.shift(1, freq="infer") - unshifted = shifted.shift(-1, freq="infer") - tm.assert_series_equal(unshifted, ps) - - shifted2 = ps.shift(freq="B") - tm.assert_series_equal(shifted, shifted2) - - shifted3 = ps.shift(freq=BDay()) - tm.assert_series_equal(shifted, shifted3) - - def test_datetime_series_shift_with_freq(self, datetime_series): - shifted = datetime_series.shift(1, freq="infer") - unshifted = shifted.shift(-1, freq="infer") - tm.assert_series_equal(datetime_series, unshifted) - - shifted2 = datetime_series.shift(freq=datetime_series.index.freq) - tm.assert_series_equal(shifted, shifted2) - - inferred_ts = Series( - datetime_series.values, Index(np.asarray(datetime_series.index)), name="ts" - ) - shifted = inferred_ts.shift(1, freq="infer") - expected = datetime_series.shift(1, freq="infer") - expected.index = expected.index._with_freq(None) - tm.assert_series_equal(shifted, expected) - - unshifted = shifted.shift(-1, freq="infer") - tm.assert_series_equal(unshifted, inferred_ts) - - def test_period_index_series_shift_with_freq_error(self): - ps = tm.makePeriodSeries() - msg = "Given freq M does not match PeriodIndex freq B" - with pytest.raises(ValueError, match=msg): - ps.shift(freq="M") - - def test_datetime_series_shift_with_freq_error(self, datetime_series): - no_freq = datetime_series[[0, 5, 7]] - msg = "Freq was not set in the index hence cannot be inferred" - with pytest.raises(ValueError, match=msg): - no_freq.shift(freq="infer") - def test_shift_int(self, datetime_series): ts = datetime_series.astype(int) shifted = ts.shift(1) From e09186f25cf999008b08f65b89ea027dc7693b01 Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 16 Dec 2021 19:31:06 -0800 Subject: [PATCH 2/7] Share tests, filter warning --- pandas/tests/frame/methods/test_shift.py | 11 ++++++++--- pandas/tests/series/methods/test_shift.py | 16 +++------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index c45b68eee35bc..b7ff66595e36e 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -353,12 +353,16 @@ def test_datetime_frame_shift_with_freq_error( def test_shift_dt64values_int_fill_deprecated(self): # GH#31971 ser = Series([pd.Timestamp("2020-01-01"), pd.Timestamp("2020-01-02")]) - df = ser.to_frame() with tm.assert_produces_warning(FutureWarning): - result = df.shift(1, fill_value=0) + result = ser.shift(1, fill_value=0) + expected = Series([pd.Timestamp(0), ser[0]]) + tm.assert_series_equal(result, expected) - expected = Series([pd.Timestamp(0), ser[0]]).to_frame() + df = ser.to_frame() + with tm.assert_produces_warning(FutureWarning): + result = df.shift(1, fill_value=0) + expected = expected.to_frame() tm.assert_frame_equal(result, expected) # axis = 1 @@ -416,6 +420,7 @@ def test_shift_dt64values_int_fill_deprecated(self): ], ids=lambda x: str(x.dtype), ) + @pytest.mark.filterwarnings("ignore:Index.ravel.*:FutureWarning") def test_shift_dt64values_axis1_invalid_fill( self, vals, as_cat, using_array_manager, request ): diff --git a/pandas/tests/series/methods/test_shift.py b/pandas/tests/series/methods/test_shift.py index f584944690a7e..a2f720e328b6e 100644 --- a/pandas/tests/series/methods/test_shift.py +++ b/pandas/tests/series/methods/test_shift.py @@ -32,10 +32,10 @@ def test_shift_always_copy(self, ser, shift_size): assert ser.shift(shift_size) is not ser @pytest.mark.parametrize("move_by_freq", [pd.Timedelta("1D"), pd.Timedelta("1min")]) - def test_datetime_shift_always_copy(self, move_by_freq): + def test_datetime_shift_always_copy(self, move_by_freq, frame_or_series): # GH#22397 - ser = Series(range(5), index=date_range("2017", periods=5)) - assert ser.shift(freq=move_by_freq) is not ser + obj = frame_or_series(range(5), index=date_range("2017", periods=5)) + assert obj.shift(freq=move_by_freq) is not obj def test_shift(self, datetime_series): shifted = datetime_series.shift(1) @@ -197,16 +197,6 @@ def test_shift_categorical(self): tm.assert_index_equal(s.values.categories, sp1.values.categories) tm.assert_index_equal(s.values.categories, sn2.values.categories) - def test_shift_dt64values_int_fill_deprecated(self): - # GH#31971 - ser = Series([pd.Timestamp("2020-01-01"), pd.Timestamp("2020-01-02")]) - - with tm.assert_produces_warning(FutureWarning): - result = ser.shift(1, fill_value=0) - - expected = Series([pd.Timestamp(0), ser[0]]) - tm.assert_series_equal(result, expected) - @pytest.mark.parametrize("periods", [1, 2, 3, 4]) def test_shift_preserve_freqstr(self, periods): # GH#21275 From 79ee07a1d73a84b575138e7eb0f30ddce502fa7f Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 16 Dec 2021 19:33:56 -0800 Subject: [PATCH 3/7] put helper in tm --- pandas/_testing/__init__.py | 5 ++++- pandas/_testing/compat.py | 10 +++++++++ pandas/tests/frame/methods/test_shift.py | 27 ++++++++++-------------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/pandas/_testing/__init__.py b/pandas/_testing/__init__.py index 639530dbfbc57..66503ac81b4d1 100644 --- a/pandas/_testing/__init__.py +++ b/pandas/_testing/__init__.py @@ -89,7 +89,10 @@ assert_timedelta_array_equal, raise_assert_detail, ) -from pandas._testing.compat import get_dtype # noqa:F401 +from pandas._testing.compat import ( # noqa:F401 + get_dtype, + get_obj, +) from pandas._testing.contexts import ( # noqa:F401 RNGContext, decompress_file, diff --git a/pandas/_testing/compat.py b/pandas/_testing/compat.py index 1b7d038214949..e2ac8f779ef0e 100644 --- a/pandas/_testing/compat.py +++ b/pandas/_testing/compat.py @@ -11,3 +11,13 @@ def get_dtype(obj): return obj.dtypes.iat[0] else: return obj.dtype + + +def get_obj(df: DataFrame, klass): + """ + For sharing tests using frame_or_series, either return the DataFrame + unchanged or return it's first column as a Series. + """ + if klass is DataFrame: + return df + return df._ixs(0, axis=1) diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index b7ff66595e36e..43352346274c7 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -15,12 +15,6 @@ import pandas._testing as tm -def get_obj(df, klass): - if klass is Series: - return df._ixs(0, axis=1) - return df - - class TestDataFrameShift: def test_shift(self, datetime_frame, frame_or_series): # naive shift @@ -56,7 +50,7 @@ def test_shift(self, datetime_frame, frame_or_series): def test_shift_with_periodindex(self, frame_or_series): # Shifting with PeriodIndex ps = tm.makePeriodFrame() - ps = get_obj(ps, frame_or_series) + ps = tm.get_obj(ps, frame_or_series) shifted = ps.shift(1) unshifted = shifted.shift(-1) @@ -244,7 +238,7 @@ def test_tshift(self, datetime_frame, frame_or_series): # PeriodIndex ps = tm.makePeriodFrame() - ps = get_obj(ps, frame_or_series) + ps = tm.get_obj(ps, frame_or_series) shifted = ps.tshift(1) unshifted = shifted.tshift(-1) @@ -261,7 +255,7 @@ def test_tshift(self, datetime_frame, frame_or_series): ps.tshift(freq="M") # DatetimeIndex - dtobj = get_obj(datetime_frame, frame_or_series) + dtobj = tm.get_obj(datetime_frame, frame_or_series) shifted = dtobj.tshift(1) unshifted = shifted.tshift(-1) @@ -275,7 +269,7 @@ def test_tshift(self, datetime_frame, frame_or_series): Index(np.asarray(datetime_frame.index)), columns=datetime_frame.columns, ) - inferred_ts = get_obj(inferred_ts, frame_or_series) + inferred_ts = tm.get_obj(inferred_ts, frame_or_series) shifted = inferred_ts.tshift(1) expected = dtobj.tshift(1) @@ -292,13 +286,13 @@ def test_tshift(self, datetime_frame, frame_or_series): def test_tshift_deprecated(self, datetime_frame, frame_or_series): # GH#11631 - dtobj = get_obj(datetime_frame, frame_or_series) + dtobj = tm.get_obj(datetime_frame, frame_or_series) with tm.assert_produces_warning(FutureWarning): dtobj.tshift() def test_period_index_frame_shift_with_freq(self, frame_or_series): ps = tm.makePeriodFrame() - ps = get_obj(ps, frame_or_series) + ps = tm.get_obj(ps, frame_or_series) shifted = ps.shift(1, freq="infer") unshifted = shifted.shift(-1, freq="infer") @@ -311,7 +305,7 @@ def test_period_index_frame_shift_with_freq(self, frame_or_series): tm.assert_equal(shifted, shifted3) def test_datetime_frame_shift_with_freq(self, datetime_frame, frame_or_series): - dtobj = get_obj(datetime_frame, frame_or_series) + dtobj = tm.get_obj(datetime_frame, frame_or_series) shifted = dtobj.shift(1, freq="infer") unshifted = shifted.shift(-1, freq="infer") tm.assert_equal(dtobj, unshifted) @@ -324,7 +318,7 @@ def test_datetime_frame_shift_with_freq(self, datetime_frame, frame_or_series): Index(np.asarray(datetime_frame.index)), columns=datetime_frame.columns, ) - inferred_ts = get_obj(inferred_ts, frame_or_series) + inferred_ts = tm.get_obj(inferred_ts, frame_or_series) shifted = inferred_ts.shift(1, freq="infer") expected = dtobj.shift(1, freq="infer") expected.index = expected.index._with_freq(None) @@ -335,7 +329,7 @@ def test_datetime_frame_shift_with_freq(self, datetime_frame, frame_or_series): def test_period_index_frame_shift_with_freq_error(self, frame_or_series): ps = tm.makePeriodFrame() - ps = get_obj(ps, frame_or_series) + ps = tm.get_obj(ps, frame_or_series) msg = "Given freq M does not match PeriodIndex freq B" with pytest.raises(ValueError, match=msg): ps.shift(freq="M") @@ -343,7 +337,7 @@ def test_period_index_frame_shift_with_freq_error(self, frame_or_series): def test_datetime_frame_shift_with_freq_error( self, datetime_frame, frame_or_series ): - dtobj = get_obj(datetime_frame, frame_or_series) + dtobj = tm.get_obj(datetime_frame, frame_or_series) no_freq = dtobj.iloc[[0, 5, 7]] msg = "Freq was not set in the index hence cannot be inferred" with pytest.raises(ValueError, match=msg): @@ -420,6 +414,7 @@ def test_shift_dt64values_int_fill_deprecated(self): ], ids=lambda x: str(x.dtype), ) + # TODO(2.0): remove filtering @pytest.mark.filterwarnings("ignore:Index.ravel.*:FutureWarning") def test_shift_dt64values_axis1_invalid_fill( self, vals, as_cat, using_array_manager, request From feb5f4247701981e30564788d3fbce4ecbd9cdfc Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 16 Dec 2021 19:42:59 -0800 Subject: [PATCH 4/7] share more shift tests --- pandas/tests/frame/methods/test_shift.py | 77 +++++++++++++++++++++ pandas/tests/series/methods/test_shift.py | 83 ----------------------- 2 files changed, 77 insertions(+), 83 deletions(-) diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index 43352346274c7..92f79e627df1e 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -8,6 +8,7 @@ CategoricalIndex, DataFrame, Index, + NaT, Series, date_range, offsets, @@ -16,6 +17,67 @@ class TestDataFrameShift: + def test_shift_int(self, datetime_frame, frame_or_series): + ts = tm.get_obj(datetime_frame, frame_or_series).astype(int) + shifted = ts.shift(1) + expected = ts.astype(float).shift(1) + tm.assert_equal(shifted, expected) + + def test_shift_32bit_take(self, frame_or_series): + # 32-bit taking + # GH#8129 + index = date_range("2000-01-01", periods=5) + for dtype in ["int32", "int64"]: + arr = np.arange(5, dtype=dtype) + s1 = frame_or_series(arr, index=index) + p = arr[1] + result = s1.shift(periods=p) + expected = frame_or_series([np.nan, 0, 1, 2, 3], index=index) + tm.assert_equal(result, expected) + + @pytest.mark.parametrize("periods", [1, 2, 3, 4]) + def test_shift_preserve_freqstr(self, periods, frame_or_series): + # GH#21275 + obj = frame_or_series( + range(periods), + index=date_range("2016-1-1 00:00:00", periods=periods, freq="H"), + ) + + result = obj.shift(1, "2H") + + expected = frame_or_series( + range(periods), + index=date_range("2016-1-1 02:00:00", periods=periods, freq="H"), + ) + tm.assert_equal(result, expected) + + def test_shift_dst(self, frame_or_series): + # GH#13926 + dates = date_range("2016-11-06", freq="H", periods=10, tz="US/Eastern") + obj = frame_or_series(dates) + + res = obj.shift(0) + tm.assert_equal(res, obj) + assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]" + + res = obj.shift(1) + exp_vals = [NaT] + dates.astype(object).values.tolist()[:9] + exp = frame_or_series(exp_vals) + tm.assert_equal(res, exp) + assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]" + + res = obj.shift(-2) + exp_vals = dates.astype(object).values.tolist()[2:] + [NaT, NaT] + exp = frame_or_series(exp_vals) + tm.assert_equal(res, exp) + assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]" + + for ex in [10, -10, 20, -20]: + res = obj.shift(ex) + exp = frame_or_series([NaT] * 10, dtype="datetime64[ns, US/Eastern]") + tm.assert_equal(res, exp) + assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]" + def test_shift(self, datetime_frame, frame_or_series): # naive shift shiftedFrame = datetime_frame.shift(5) @@ -120,6 +182,21 @@ def test_shift_categorical(self): xp = DataFrame({"one": s1.shift(1), "two": s2.shift(1)}) tm.assert_frame_equal(rs, xp) + def test_shift_categorical_fill_value(self, frame_or_series): + ts = frame_or_series(["a", "b", "c", "d"], dtype="category") + res = ts.shift(1, fill_value="a") + expected = frame_or_series( + pd.Categorical( + ["a", "a", "b", "c"], categories=["a", "b", "c", "d"], ordered=False + ) + ) + tm.assert_equal(res, expected) + + # check for incorrect fill_value + msg = r"Cannot setitem on a Categorical with a new category \(f\)" + with pytest.raises(TypeError, match=msg): + ts.shift(1, fill_value="f") + def test_shift_fill_value(self, frame_or_series): # GH#24128 dti = date_range("1/1/2000", periods=5, freq="H") diff --git a/pandas/tests/series/methods/test_shift.py b/pandas/tests/series/methods/test_shift.py index a2f720e328b6e..68de3fa4ec518 100644 --- a/pandas/tests/series/methods/test_shift.py +++ b/pandas/tests/series/methods/test_shift.py @@ -3,10 +3,8 @@ from pandas.errors import NullFrequencyError -import pandas as pd from pandas import ( DatetimeIndex, - NaT, Series, TimedeltaIndex, date_range, @@ -31,12 +29,6 @@ def test_shift_always_copy(self, ser, shift_size): # GH22397 assert ser.shift(shift_size) is not ser - @pytest.mark.parametrize("move_by_freq", [pd.Timedelta("1D"), pd.Timedelta("1min")]) - def test_datetime_shift_always_copy(self, move_by_freq, frame_or_series): - # GH#22397 - obj = frame_or_series(range(5), index=date_range("2017", periods=5)) - assert obj.shift(freq=move_by_freq) is not obj - def test_shift(self, datetime_series): shifted = datetime_series.shift(1) unshifted = shifted.shift(-1) @@ -65,17 +57,6 @@ def test_shift(self, datetime_series): unshifted = datetime_series.shift(0) tm.assert_series_equal(unshifted, datetime_series) - def test_shift_32bit_take(self): - # 32-bit taking - # GH#8129 - index = date_range("2000-01-01", periods=5) - for dtype in ["int32", "int64"]: - s1 = Series(np.arange(5, dtype=dtype), index=index) - p = s1.iloc[1] - result = s1.shift(periods=p) - expected = Series([np.nan, 0, 1, 2, 3], index=index) - tm.assert_series_equal(result, expected) - def test_shift_with_tz(self): # GH#8260 # with tz @@ -112,54 +93,6 @@ def test_shift2(self): with pytest.raises(NullFrequencyError, match=msg): idx.shift(1) - def test_shift_categorical_fill_value(self): - ts = Series(["a", "b", "c", "d"], dtype="category") - res = ts.shift(1, fill_value="a") - expected = Series( - pd.Categorical( - ["a", "a", "b", "c"], categories=["a", "b", "c", "d"], ordered=False - ) - ) - tm.assert_equal(res, expected) - - # check for incorrect fill_value - msg = r"Cannot setitem on a Categorical with a new category \(f\)" - with pytest.raises(TypeError, match=msg): - ts.shift(1, fill_value="f") - - def test_shift_dst(self): - # GH#13926 - dates = date_range("2016-11-06", freq="H", periods=10, tz="US/Eastern") - s = Series(dates) - - res = s.shift(0) - tm.assert_series_equal(res, s) - assert res.dtype == "datetime64[ns, US/Eastern]" - - res = s.shift(1) - exp_vals = [NaT] + dates.astype(object).values.tolist()[:9] - exp = Series(exp_vals) - tm.assert_series_equal(res, exp) - assert res.dtype == "datetime64[ns, US/Eastern]" - - res = s.shift(-2) - exp_vals = dates.astype(object).values.tolist()[2:] + [NaT, NaT] - exp = Series(exp_vals) - tm.assert_series_equal(res, exp) - assert res.dtype == "datetime64[ns, US/Eastern]" - - for ex in [10, -10, 20, -20]: - res = s.shift(ex) - exp = Series([NaT] * 10, dtype="datetime64[ns, US/Eastern]") - tm.assert_series_equal(res, exp) - assert res.dtype == "datetime64[ns, US/Eastern]" - - def test_shift_int(self, datetime_series): - ts = datetime_series.astype(int) - shifted = ts.shift(1) - expected = ts.astype(float).shift(1) - tm.assert_series_equal(shifted, expected) - def test_shift_object_non_scalar_fill(self): # shift requires scalar fill_value except for object dtype ser = Series(range(3)) @@ -197,22 +130,6 @@ def test_shift_categorical(self): tm.assert_index_equal(s.values.categories, sp1.values.categories) tm.assert_index_equal(s.values.categories, sn2.values.categories) - @pytest.mark.parametrize("periods", [1, 2, 3, 4]) - def test_shift_preserve_freqstr(self, periods): - # GH#21275 - ser = Series( - range(periods), - index=date_range("2016-1-1 00:00:00", periods=periods, freq="H"), - ) - - result = ser.shift(1, "2H") - - expected = Series( - range(periods), - index=date_range("2016-1-1 02:00:00", periods=periods, freq="H"), - ) - tm.assert_series_equal(result, expected) - @pytest.mark.parametrize( "input_data, output_data", [(np.empty(shape=(0,)), []), (np.ones(shape=(2,)), [np.nan, 1.0])], From 89ed848b929a228483555007902e5a73aa20a2e4 Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 16 Dec 2021 19:55:26 -0800 Subject: [PATCH 5/7] share more --- pandas/tests/frame/methods/test_shift.py | 40 +++++++++++++++-------- pandas/tests/series/methods/test_shift.py | 20 ------------ 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index 92f79e627df1e..7de7c24d9f6de 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -78,7 +78,13 @@ def test_shift_dst(self, frame_or_series): tm.assert_equal(res, exp) assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]" - def test_shift(self, datetime_frame, frame_or_series): + def test_shift_by_zero(self, datetime_frame, frame_or_series): + # shift by 0 + obj = tm.get_obj(datetime_frame, frame_or_series) + unshifted = obj.shift(0) + tm.assert_equal(unshifted, obj) + + def test_shift(self, datetime_frame): # naive shift shiftedFrame = datetime_frame.shift(5) tm.assert_index_equal(shiftedFrame.index, datetime_frame.index) @@ -92,22 +98,28 @@ def test_shift(self, datetime_frame, frame_or_series): shiftedSeries = datetime_frame["A"].shift(-5) tm.assert_series_equal(shiftedFrame["A"], shiftedSeries) - # shift by 0 - unshifted = datetime_frame.shift(0) - tm.assert_frame_equal(unshifted, datetime_frame) - + def test_shift_by_offset(self, datetime_frame, frame_or_series): # shift by DateOffset - shiftedFrame = datetime_frame.shift(5, freq=offsets.BDay()) - assert len(shiftedFrame) == len(datetime_frame) + obj = tm.get_obj(datetime_frame, frame_or_series) + offset = offsets.BDay() - shiftedFrame2 = datetime_frame.shift(5, freq="B") - tm.assert_frame_equal(shiftedFrame, shiftedFrame2) + shifted = obj.shift(5, freq=offset) + assert len(shifted) == len(obj) + unshifted = shifted.shift(-5, freq=offset) + tm.assert_equal(unshifted, obj) - d = datetime_frame.index[0] - shifted_d = d + offsets.BDay(5) - tm.assert_series_equal( - datetime_frame.xs(d), shiftedFrame.xs(shifted_d), check_names=False - ) + shifted2 = obj.shift(5, freq="B") + tm.assert_equal(shifted, shifted2) + + unshifted = obj.shift(0, freq=offset) + tm.assert_equal(unshifted, obj) + + d = obj.index[0] + shifted_d = d + offset * 5 + if frame_or_series is DataFrame: + tm.assert_series_equal(obj.xs(d), shifted.xs(shifted_d), check_names=False) + else: + tm.assert_almost_equal(obj.at[d], shifted.at[shifted_d]) def test_shift_with_periodindex(self, frame_or_series): # Shifting with PeriodIndex diff --git a/pandas/tests/series/methods/test_shift.py b/pandas/tests/series/methods/test_shift.py index 68de3fa4ec518..5b0b44ff45ce0 100644 --- a/pandas/tests/series/methods/test_shift.py +++ b/pandas/tests/series/methods/test_shift.py @@ -12,8 +12,6 @@ ) import pandas._testing as tm -from pandas.tseries.offsets import BDay - class TestShift: @pytest.mark.parametrize( @@ -39,24 +37,6 @@ def test_shift(self, datetime_series): unshifted.dropna().values, datetime_series.values[:-1] ) - offset = BDay() - shifted = datetime_series.shift(1, freq=offset) - unshifted = shifted.shift(-1, freq=offset) - - tm.assert_series_equal(unshifted, datetime_series) - - unshifted = datetime_series.shift(0, freq=offset) - tm.assert_series_equal(unshifted, datetime_series) - - shifted = datetime_series.shift(1, freq="B") - unshifted = shifted.shift(-1, freq="B") - - tm.assert_series_equal(unshifted, datetime_series) - - # corner case - unshifted = datetime_series.shift(0) - tm.assert_series_equal(unshifted, datetime_series) - def test_shift_with_tz(self): # GH#8260 # with tz From 5c0014681cca83210d8eb26ed6e427fb293ac45a Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 16 Dec 2021 20:01:35 -0800 Subject: [PATCH 6/7] share more --- pandas/tests/frame/methods/test_shift.py | 26 ++++++++++++++++------- pandas/tests/series/methods/test_shift.py | 10 --------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index 7de7c24d9f6de..806cd4c625974 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -86,17 +86,27 @@ def test_shift_by_zero(self, datetime_frame, frame_or_series): def test_shift(self, datetime_frame): # naive shift - shiftedFrame = datetime_frame.shift(5) - tm.assert_index_equal(shiftedFrame.index, datetime_frame.index) + ser = datetime_frame["A"] - shiftedSeries = datetime_frame["A"].shift(5) - tm.assert_series_equal(shiftedFrame["A"], shiftedSeries) + shifted = datetime_frame.shift(5) + tm.assert_index_equal(shifted.index, datetime_frame.index) - shiftedFrame = datetime_frame.shift(-5) - tm.assert_index_equal(shiftedFrame.index, datetime_frame.index) + shifted_ser = ser.shift(5) + tm.assert_series_equal(shifted["A"], shifted_ser) - shiftedSeries = datetime_frame["A"].shift(-5) - tm.assert_series_equal(shiftedFrame["A"], shiftedSeries) + shifted = datetime_frame.shift(-5) + tm.assert_index_equal(shifted.index, datetime_frame.index) + + shifted_ser = ser.shift(-5) + tm.assert_series_equal(shifted["A"], shifted_ser) + + unshifted = datetime_frame.shift(5).shift(-5) + tm.assert_numpy_array_equal( + unshifted.dropna().values, datetime_frame.values[:-5] + ) + + unshifted_ser = ser.shift(5).shift(-5) + tm.assert_numpy_array_equal(unshifted_ser.dropna().values, ser.values[:-5]) def test_shift_by_offset(self, datetime_frame, frame_or_series): # shift by DateOffset diff --git a/pandas/tests/series/methods/test_shift.py b/pandas/tests/series/methods/test_shift.py index 5b0b44ff45ce0..ea21aea122351 100644 --- a/pandas/tests/series/methods/test_shift.py +++ b/pandas/tests/series/methods/test_shift.py @@ -27,16 +27,6 @@ def test_shift_always_copy(self, ser, shift_size): # GH22397 assert ser.shift(shift_size) is not ser - def test_shift(self, datetime_series): - shifted = datetime_series.shift(1) - unshifted = shifted.shift(-1) - - tm.assert_index_equal(shifted.index, datetime_series.index) - tm.assert_index_equal(unshifted.index, datetime_series.index) - tm.assert_numpy_array_equal( - unshifted.dropna().values, datetime_series.values[:-1] - ) - def test_shift_with_tz(self): # GH#8260 # with tz From 3b900af4f5827094223e87658420e95285a074f8 Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 16 Dec 2021 20:46:29 -0800 Subject: [PATCH 7/7] share the rest --- pandas/tests/frame/methods/test_shift.py | 96 ++++++++++++++++++ pandas/tests/series/methods/test_shift.py | 114 ---------------------- 2 files changed, 96 insertions(+), 114 deletions(-) delete mode 100644 pandas/tests/series/methods/test_shift.py diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index 806cd4c625974..c92e3dbe27439 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -17,6 +17,75 @@ class TestDataFrameShift: + @pytest.mark.parametrize( + "input_data, output_data", + [(np.empty(shape=(0,)), []), (np.ones(shape=(2,)), [np.nan, 1.0])], + ) + def test_shift_non_writable_array(self, input_data, output_data, frame_or_series): + # GH21049 Verify whether non writable numpy array is shiftable + input_data.setflags(write=False) + + result = frame_or_series(input_data).shift(1) + if frame_or_series is not Series: + # need to explicitly specify columns in the empty case + expected = frame_or_series( + output_data, + index=range(len(output_data)), + columns=range(1), + dtype="float64", + ) + else: + expected = frame_or_series(output_data, dtype="float64") + + tm.assert_equal(result, expected) + + def test_shift_mismatched_freq(self, frame_or_series): + ts = frame_or_series( + np.random.randn(5), index=date_range("1/1/2000", periods=5, freq="H") + ) + + result = ts.shift(1, freq="5T") + exp_index = ts.index.shift(1, freq="5T") + tm.assert_index_equal(result.index, exp_index) + + # GH#1063, multiple of same base + result = ts.shift(1, freq="4H") + exp_index = ts.index + offsets.Hour(4) + tm.assert_index_equal(result.index, exp_index) + + @pytest.mark.parametrize( + "obj", + [ + Series([np.arange(5)]), + date_range("1/1/2011", periods=24, freq="H"), + Series(range(5), index=date_range("2017", periods=5)), + ], + ) + @pytest.mark.parametrize("shift_size", [0, 1, 2]) + def test_shift_always_copy(self, obj, shift_size, frame_or_series): + # GH#22397 + if frame_or_series is not Series: + obj = obj.to_frame() + assert obj.shift(shift_size) is not obj + + def test_shift_object_non_scalar_fill(self): + # shift requires scalar fill_value except for object dtype + ser = Series(range(3)) + with pytest.raises(ValueError, match="fill_value must be a scalar"): + ser.shift(1, fill_value=[]) + + df = ser.to_frame() + with pytest.raises(ValueError, match="fill_value must be a scalar"): + df.shift(1, fill_value=np.arange(3)) + + obj_ser = ser.astype(object) + result = obj_ser.shift(1, fill_value={}) + assert result[0] == {} + + obj_df = obj_ser.to_frame() + result = obj_df.shift(1, fill_value={}) + assert result.iloc[0, 0] == {} + def test_shift_int(self, datetime_frame, frame_or_series): ts = tm.get_obj(datetime_frame, frame_or_series).astype(int) shifted = ts.shift(1) @@ -195,6 +264,33 @@ def test_shift_bool(self): ) tm.assert_frame_equal(rs, xp) + def test_shift_categorical1(self, frame_or_series): + # GH#9416 + obj = frame_or_series(["a", "b", "c", "d"], dtype="category") + + rt = obj.shift(1).shift(-1) + tm.assert_equal(obj.iloc[:-1], rt.dropna()) + + def get_cat_values(ndframe): + # For Series we could just do ._values; for DataFrame + # we may be able to do this if we ever have 2D Categoricals + return ndframe._mgr.arrays[0] + + cat = get_cat_values(obj) + + sp1 = obj.shift(1) + tm.assert_index_equal(obj.index, sp1.index) + assert np.all(get_cat_values(sp1).codes[:1] == -1) + assert np.all(cat.codes[:-1] == get_cat_values(sp1).codes[1:]) + + sn2 = obj.shift(-2) + tm.assert_index_equal(obj.index, sn2.index) + assert np.all(get_cat_values(sn2).codes[-2:] == -1) + assert np.all(cat.codes[2:] == get_cat_values(sn2).codes[:-2]) + + tm.assert_index_equal(cat.categories, get_cat_values(sp1).categories) + tm.assert_index_equal(cat.categories, get_cat_values(sn2).categories) + def test_shift_categorical(self): # GH#9416 s1 = Series(["a", "b", "c"], dtype="category") diff --git a/pandas/tests/series/methods/test_shift.py b/pandas/tests/series/methods/test_shift.py deleted file mode 100644 index ea21aea122351..0000000000000 --- a/pandas/tests/series/methods/test_shift.py +++ /dev/null @@ -1,114 +0,0 @@ -import numpy as np -import pytest - -from pandas.errors import NullFrequencyError - -from pandas import ( - DatetimeIndex, - Series, - TimedeltaIndex, - date_range, - offsets, -) -import pandas._testing as tm - - -class TestShift: - @pytest.mark.parametrize( - "ser", - [ - Series([np.arange(5)]), - date_range("1/1/2011", periods=24, freq="H"), - Series(range(5), index=date_range("2017", periods=5)), - ], - ) - @pytest.mark.parametrize("shift_size", [0, 1, 2]) - def test_shift_always_copy(self, ser, shift_size): - # GH22397 - assert ser.shift(shift_size) is not ser - - def test_shift_with_tz(self): - # GH#8260 - # with tz - s = Series( - date_range("2000-01-01 09:00:00", periods=5, tz="US/Eastern"), name="foo" - ) - result = s - s.shift() - - exp = Series(TimedeltaIndex(["NaT"] + ["1 days"] * 4), name="foo") - tm.assert_series_equal(result, exp) - - # incompat tz - s2 = Series(date_range("2000-01-01 09:00:00", periods=5, tz="CET"), name="foo") - msg = "DatetimeArray subtraction must have the same timezones or no timezones" - with pytest.raises(TypeError, match=msg): - s - s2 - - def test_shift2(self): - ts = Series( - np.random.randn(5), index=date_range("1/1/2000", periods=5, freq="H") - ) - - result = ts.shift(1, freq="5T") - exp_index = ts.index.shift(1, freq="5T") - tm.assert_index_equal(result.index, exp_index) - - # GH#1063, multiple of same base - result = ts.shift(1, freq="4H") - exp_index = ts.index + offsets.Hour(4) - tm.assert_index_equal(result.index, exp_index) - - idx = DatetimeIndex(["2000-01-01", "2000-01-02", "2000-01-04"]) - msg = "Cannot shift with no freq" - with pytest.raises(NullFrequencyError, match=msg): - idx.shift(1) - - def test_shift_object_non_scalar_fill(self): - # shift requires scalar fill_value except for object dtype - ser = Series(range(3)) - with pytest.raises(ValueError, match="fill_value must be a scalar"): - ser.shift(1, fill_value=[]) - - df = ser.to_frame() - with pytest.raises(ValueError, match="fill_value must be a scalar"): - df.shift(1, fill_value=np.arange(3)) - - obj_ser = ser.astype(object) - result = obj_ser.shift(1, fill_value={}) - assert result[0] == {} - - obj_df = obj_ser.to_frame() - result = obj_df.shift(1, fill_value={}) - assert result.iloc[0, 0] == {} - - def test_shift_categorical(self): - # GH#9416 - s = Series(["a", "b", "c", "d"], dtype="category") - - tm.assert_series_equal(s.iloc[:-1], s.shift(1).shift(-1).dropna()) - - sp1 = s.shift(1) - tm.assert_index_equal(s.index, sp1.index) - assert np.all(sp1.values.codes[:1] == -1) - assert np.all(s.values.codes[:-1] == sp1.values.codes[1:]) - - sn2 = s.shift(-2) - tm.assert_index_equal(s.index, sn2.index) - assert np.all(sn2.values.codes[-2:] == -1) - assert np.all(s.values.codes[2:] == sn2.values.codes[:-2]) - - tm.assert_index_equal(s.values.categories, sp1.values.categories) - tm.assert_index_equal(s.values.categories, sn2.values.categories) - - @pytest.mark.parametrize( - "input_data, output_data", - [(np.empty(shape=(0,)), []), (np.ones(shape=(2,)), [np.nan, 1.0])], - ) - def test_shift_non_writable_array(self, input_data, output_data): - # GH21049 Verify whether non writable numpy array is shiftable - input_data.setflags(write=False) - - result = Series(input_data).shift(1) - expected = Series(output_data, dtype="float64") - - tm.assert_series_equal(result, expected)