diff --git a/doc/source/release.rst b/doc/source/release.rst index af9611bb98fae..d331dc7e164fc 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -311,6 +311,7 @@ API Changes - Provide __dir__ method (and local context) for tab completion / remove ipython completers code (:issue:`4501`) - Support non-unique axes in a Panel via indexing operations (:issue:`4960`) + - ``.truncate`` will raise a ``ValueError`` if invalid before and afters dates are given (:issue:`5242`) Internal Refactoring ~~~~~~~~~~~~~~~~~~~~ diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 16f4118d5d1df..266253e05ed61 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2813,7 +2813,7 @@ def tshift(self, periods=1, freq=None, axis=0, **kwds): return self._constructor(new_data).__finalize__(self) - def truncate(self, before=None, after=None, copy=True): + def truncate(self, before=None, after=None, axis=None, copy=True): """Truncates a sorted NDFrame before and/or after some particular dates. @@ -2823,28 +2823,38 @@ def truncate(self, before=None, after=None, copy=True): Truncate before date after : date Truncate after date + axis : the truncation axis, defaults to the stat axis + copy : boolean, default is True, + return a copy of the truncated section Returns ------- truncated : type of caller """ + if axis is None: + axis = self._stat_axis_number + axis = self._get_axis_number(axis) + ax = self._get_axis(axis) + # if we have a date index, convert to dates, otherwise # treat like a slice - if self.index.is_all_dates: + if ax.is_all_dates: from pandas.tseries.tools import to_datetime before = to_datetime(before) after = to_datetime(after) if before is not None and after is not None: if before > after: - raise AssertionError('Truncate: %s must be after %s' % - (after, before)) + raise ValueError('Truncate: %s must be after %s' % + (after, before)) - result = self.ix[before:after] + slicer = [ slice(None, None) ] * self._AXIS_LEN + slicer[axis] = slice(before,after) + result = self.ix[tuple(slicer)] - if isinstance(self.index, MultiIndex): - result.index = self.index.truncate(before, after) + if isinstance(ax, MultiIndex): + setattr(result,self._get_axis_name(axis),ax.truncate(before, after)) if copy: result = result.copy() diff --git a/pandas/core/panel.py b/pandas/core/panel.py index 87e9121b2dffc..a86c186e26b53 100644 --- a/pandas/core/panel.py +++ b/pandas/core/panel.py @@ -998,30 +998,6 @@ def shift(self, lags, freq=None, axis='major'): def tshift(self, periods=1, freq=None, axis='major', **kwds): return super(Panel, self).tshift(periods, freq, axis, **kwds) - def truncate(self, before=None, after=None, axis='major'): - """Function truncates a sorted Panel before and/or after some - particular values on the requested axis - - Parameters - ---------- - before : date - Left boundary - after : date - Right boundary - axis : {'major', 'minor', 'items'} - - Returns - ------- - Panel - """ - axis = self._get_axis_name(axis) - index = self._get_axis(axis) - - beg_slice, end_slice = index.slice_locs(before, after) - new_index = index[beg_slice:end_slice] - - return self.reindex(**{axis: new_index}) - def join(self, other, how='left', lsuffix='', rsuffix=''): """ Join items with other Panel either on major and minor axes column diff --git a/pandas/sparse/panel.py b/pandas/sparse/panel.py index 74bca7de89bcc..86dcf97c8bd3d 100644 --- a/pandas/sparse/panel.py +++ b/pandas/sparse/panel.py @@ -187,6 +187,15 @@ def _ixs(self, i, axis=0): return self.xs(key, axis=axis) + def _slice(self, slobj, axis=0, raise_on_error=False, typ=None): + """ + for compat as we don't support Block Manager here + """ + axis = self._get_axis_name(axis) + index = self._get_axis(axis) + + return self.reindex(**{axis: index[slobj]}) + def _get_item_cache(self, key): return self._frames[key] diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index fe0f9244c31a3..d74ea8a5d2ffc 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -7731,6 +7731,10 @@ def test_truncate(self): truncated = ts.truncate(after=end_missing) assert_frame_equal(truncated, expected) + self.assertRaises(ValueError, ts.truncate, + before=ts.index[-1] - 1, + after=ts.index[0] +1) + def test_truncate_copy(self): index = self.tsframe.index truncated = self.tsframe.truncate(index[5], index[10]) diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 3715de6dffeb9..645533d5629d2 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -3899,7 +3899,7 @@ def test_truncate(self): truncated = ts.truncate(before=self.ts.index[-1] + offset) assert(len(truncated) == 0) - self.assertRaises(Exception, ts.truncate, + self.assertRaises(ValueError, ts.truncate, before=self.ts.index[-1] + offset, after=self.ts.index[0] - offset)