From 5e7bf20cf143b5764b25a93858a9b2f78e19e3bd Mon Sep 17 00:00:00 2001 From: Dale Jung Date: Thu, 24 Apr 2014 18:57:33 -0400 Subject: [PATCH 1/2] ENH: Added NDFrame.slice_shift added slice_shift func docs and removed freq argument --- pandas/core/generic.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 3f2ecd8afd2d4..aa45f072a72ac 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -3227,6 +3227,42 @@ def shift(self, periods=1, freq=None, axis=0, **kwds): return self._constructor(new_data).__finalize__(self) + def slice_shift(self, periods=1, axis=0, **kwds): + """ + Equivalent to `shift` without copying data. The shifted data will + not include the dropped periods and the shifted axis will be smaller + than the original. + + Parameters + ---------- + periods : int + Number of periods to move, can be positive or negative + + Notes + ----- + While the `slice_shift` is faster than `shift`, you may pay for it + later during alignment. + + Returns + ------- + shifted : same type as caller + """ + if periods == 0: + return self + + if periods > 0: + vslicer = slice(None, -periods) + islicer = slice(periods, None) + else: + vslicer = slice(-periods, None) + islicer = slice(None, periods) + + new_obj = self._slice(vslicer, axis=axis) + shifted_axis = self._get_axis(axis)[islicer] + new_obj.set_axis(axis, shifted_axis) + + return new_obj.__finalize__(self) + def tshift(self, periods=1, freq=None, axis=0, **kwds): """ Shift the time index, using the index's frequency if available From 81675b651bc9aa04c1edaf1307aa72168f01abbb Mon Sep 17 00:00:00 2001 From: Dale Jung Date: Thu, 24 Apr 2014 19:06:27 -0400 Subject: [PATCH 2/2] BUG: Change Panel.shift to use slice_shift #6605 #6826 TST: Make sure Panel.shift retains dtypes DOC: removed previous doc entries for #6605 Re-add note about dropping shifted periods DOC: added note about bug fix don't pass on freq --- doc/source/release.rst | 2 +- doc/source/v0.14.0.txt | 1 - pandas/core/panel.py | 5 +++-- pandas/tests/test_panel.py | 12 ++++++++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index c975143b0ef67..4eb40818ce4e5 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -151,7 +151,6 @@ API Changes to a non-unique item in the ``Index`` (previously raised a ``KeyError``). (:issue:`6738`) - all offset operations now return ``Timestamp`` types (rather than datetime), Business/Week frequencies were incorrect (:issue:`4069`) - ``Series.iteritems()`` is now lazy (returns an iterator rather than a list). This was the documented behavior prior to 0.14. (:issue:`6760`) -- ``Panel.shift`` now uses ``NDFrame.shift``. It no longer drops the ``nan`` data and retains its original shape. (:issue:`4867`) - ``to_excel`` now converts ``np.inf`` into a string representation, customizable by the ``inf_rep`` keyword argument (Excel has no native inf representation) (:issue:`6782`) @@ -424,6 +423,7 @@ Bug Fixes - Bug in ``DataFrame.apply`` with functions that used *args or **kwargs and returned an empty result (:issue:`6952`) - Bug in sum/mean on 32-bit platforms on overflows (:issue:`6915`) +- Moved ``Panel.shift`` to ``NDFrame.slice_shift`` and fixed to respect multiple dtypes. (:issue:`6959`) pandas 0.13.1 ------------- diff --git a/doc/source/v0.14.0.txt b/doc/source/v0.14.0.txt index 34480668df8c9..6743ee5981e57 100644 --- a/doc/source/v0.14.0.txt +++ b/doc/source/v0.14.0.txt @@ -199,7 +199,6 @@ API changes covs[df.index[-1]] - ``Series.iteritems()`` is now lazy (returns an iterator rather than a list). This was the documented behavior prior to 0.14. (:issue:`6760`) -- ``Panel.shift`` now uses ``NDFrame.shift``. It no longer drops the ``nan`` data and retains its original shape. (:issue:`4867`) - Added ``nunique`` and ``value_counts`` functions to ``Index`` for counting unique elements. (:issue:`6734`) - ``stack`` and ``unstack`` now raise a ``ValueError`` when the ``level`` keyword refers diff --git a/pandas/core/panel.py b/pandas/core/panel.py index 5eccf49dd9e42..757bef0d1526d 100644 --- a/pandas/core/panel.py +++ b/pandas/core/panel.py @@ -1154,7 +1154,8 @@ def count(self, axis='major'): @deprecate_kwarg(old_arg_name='lags', new_arg_name='periods') def shift(self, periods=1, freq=None, axis='major'): """ - Shift major or minor axis by specified number of leads/lags. + Shift major or minor axis by specified number of leads/lags. Drops + periods right now compared with DataFrame.shift Parameters ---------- @@ -1171,7 +1172,7 @@ def shift(self, periods=1, freq=None, axis='major'): if axis == 'items': raise ValueError('Invalid axis') - return super(Panel, self).shift(periods, freq=freq, axis=axis) + return super(Panel, self).slice_shift(periods, axis=axis) def tshift(self, periods=1, freq=None, axis='major', **kwds): return super(Panel, self).tshift(periods, freq, axis, **kwds) diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py index 21207a6f97ddd..04749073166d0 100644 --- a/pandas/tests/test_panel.py +++ b/pandas/tests/test_panel.py @@ -21,7 +21,8 @@ assert_almost_equal, ensure_clean, assertRaisesRegexp, - makeCustomDataframe as mkdf + makeCustomDataframe as mkdf, + makeMixedDataFrame ) import pandas.core.panel as panelm import pandas.util.testing as tm @@ -1652,10 +1653,17 @@ def test_shift(self): # negative numbers, #2164 result = self.panel.shift(-1) - expected = Panel(dict((i, f.shift(-1)) + expected = Panel(dict((i, f.shift(-1)[:-1]) for i, f in compat.iteritems(self.panel))) assert_panel_equal(result, expected) + # mixed dtypes #6959 + data = [('item '+ch, makeMixedDataFrame()) for ch in list('abcde')] + data = dict(data) + mixed_panel = Panel.from_dict(data, orient='minor') + shifted = mixed_panel.shift(1) + assert_series_equal(mixed_panel.dtypes, shifted.dtypes) + def test_tshift(self): # PeriodIndex ps = tm.makePeriodPanel()