Skip to content

Commit c1406a3

Browse files
reidy-pjreback
authored andcommitted
ERR: Improve error message on non-sorted input with .truncate (#17984)
1 parent a26b676 commit c1406a3

File tree

5 files changed

+52
-3
lines changed

5 files changed

+52
-3
lines changed

doc/source/whatsnew/v0.22.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ Other API Changes
4646
- :class:`Timestamp` will no longer silently ignore invalid ``freq`` arguments (:issue:`5168`)
4747
- :class:`CacheableOffset` and :class:`WeekDay` are no longer available in the ``pandas.tseries.offsets`` module (:issue:`17830`)
4848
- `tseries.frequencies.get_freq_group()` and `tseries.frequencies.DAYS` are removed from the public API (:issue:`18034`)
49+
- :func:`Series.truncate` and :func:`DataFrame.truncate` will raise a ``ValueError`` if the index is not sorted instead of an unhelpful ``KeyError`` (:issue:`17935`)
50+
4951

5052
.. _whatsnew_0220.deprecations:
5153

pandas/core/generic.py

+5
Original file line numberDiff line numberDiff line change
@@ -6338,6 +6338,11 @@ def truncate(self, before=None, after=None, axis=None, copy=True):
63386338
axis = self._get_axis_number(axis)
63396339
ax = self._get_axis(axis)
63406340

6341+
# GH 17935
6342+
# Check that index is sorted
6343+
if not ax.is_monotonic_increasing and not ax.is_monotonic_decreasing:
6344+
raise ValueError("truncate requires a sorted index")
6345+
63416346
# if we have a date index, convert to dates, otherwise
63426347
# treat like a slice
63436348
if ax.is_all_dates:

pandas/tests/frame/test_timeseries.py

+27
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,33 @@ def test_truncate_copy(self):
377377
truncated.values[:] = 5.
378378
assert not (self.tsframe.values[5:11] == 5).any()
379379

380+
def test_truncate_nonsortedindex(self):
381+
# GH 17935
382+
383+
df = pd.DataFrame({'A': ['a', 'b', 'c', 'd', 'e']},
384+
index=[5, 3, 2, 9, 0])
385+
with tm.assert_raises_regex(ValueError,
386+
'truncate requires a sorted index'):
387+
df.truncate(before=3, after=9)
388+
389+
rng = pd.date_range('2011-01-01', '2012-01-01', freq='W')
390+
ts = pd.DataFrame({'A': np.random.randn(len(rng)),
391+
'B': np.random.randn(len(rng))},
392+
index=rng)
393+
with tm.assert_raises_regex(ValueError,
394+
'truncate requires a sorted index'):
395+
ts.sort_values('A', ascending=False).truncate(before='2011-11',
396+
after='2011-12')
397+
398+
df = pd.DataFrame({3: np.random.randn(5),
399+
20: np.random.randn(5),
400+
2: np.random.randn(5),
401+
0: np.random.randn(5)},
402+
columns=[3, 20, 2, 0])
403+
with tm.assert_raises_regex(ValueError,
404+
'truncate requires a sorted index'):
405+
df.truncate(before=2, after=20, axis=1)
406+
380407
def test_asfreq(self):
381408
offset_monthly = self.tsframe.asfreq(offsets.BMonthEnd())
382409
rule_monthly = self.tsframe.asfreq('BM')

pandas/tests/series/test_period.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,9 @@ def test_truncate(self):
272272
pd.Period('2017-09-03')
273273
])
274274
series2 = pd.Series([1, 2, 3], index=idx2)
275-
result2 = series2.truncate(after='2017-09-02')
275+
result2 = series2.sort_index().truncate(after='2017-09-02')
276276

277277
expected_idx2 = pd.PeriodIndex([
278-
pd.Period('2017-09-03'),
279278
pd.Period('2017-09-02')
280279
])
281-
tm.assert_series_equal(result2, pd.Series([1, 2], index=expected_idx2))
280+
tm.assert_series_equal(result2, pd.Series([2], index=expected_idx2))

pandas/tests/series/test_timeseries.py

+16
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,22 @@ def test_truncate(self):
236236
before=self.ts.index[-1] + offset,
237237
after=self.ts.index[0] - offset)
238238

239+
def test_truncate_nonsortedindex(self):
240+
# GH 17935
241+
242+
s = pd.Series(['a', 'b', 'c', 'd', 'e'],
243+
index=[5, 3, 2, 9, 0])
244+
with tm.assert_raises_regex(ValueError,
245+
'truncate requires a sorted index'):
246+
s.truncate(before=3, after=9)
247+
248+
rng = pd.date_range('2011-01-01', '2012-01-01', freq='W')
249+
ts = pd.Series(np.random.randn(len(rng)), index=rng)
250+
with tm.assert_raises_regex(ValueError,
251+
'truncate requires a sorted index'):
252+
ts.sort_values(ascending=False).truncate(before='2011-11',
253+
after='2011-12')
254+
239255
def test_asfreq(self):
240256
ts = Series([0., 1., 2.], index=[datetime(2009, 10, 30), datetime(
241257
2009, 11, 30), datetime(2009, 12, 31)])

0 commit comments

Comments
 (0)