Skip to content

Commit 79a184a

Browse files
authored
BUG: Fix for #37454: allow reversed axis when plotting with TimedeltaIndex (#37469)
1 parent 687e756 commit 79a184a

File tree

4 files changed

+27
-2
lines changed

4 files changed

+27
-2
lines changed

doc/source/whatsnew/v1.2.0.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -659,9 +659,10 @@ Plotting
659659
- Bug in :meth:`DataFrame.plot` was rotating xticklabels when ``subplots=True``, even if the x-axis wasn't an irregular time series (:issue:`29460`)
660660
- Bug in :meth:`DataFrame.plot` where a marker letter in the ``style`` keyword sometimes causes a ``ValueError`` (:issue:`21003`)
661661
- Twinned axes were losing their tick labels which should only happen to all but the last row or column of 'externally' shared axes (:issue:`33819`)
662+
- Bug in :meth:`Series.plot` and :meth:`DataFrame.plot` was throwing :exc:`ValueError` with a :class:`Series` or :class:`DataFrame`
663+
indexed by a :class:`TimedeltaIndex` with a fixed frequency when x-axis lower limit was greater than upper limit (:issue:`37454`)
662664
- Bug in :meth:`DataFrameGroupBy.boxplot` when ``subplots=False``, a KeyError would raise (:issue:`16748`)
663665

664-
665666
Groupby/resample/rolling
666667
^^^^^^^^^^^^^^^^^^^^^^^^
667668

pandas/plotting/_matplotlib/converter.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,7 @@ def format_timedelta_ticks(x, pos, n_decimals: int) -> str:
10721072

10731073
def __call__(self, x, pos=0) -> str:
10741074
(vmin, vmax) = tuple(self.axis.get_view_interval())
1075-
n_decimals = int(np.ceil(np.log10(100 * 1e9 / (vmax - vmin))))
1075+
n_decimals = int(np.ceil(np.log10(100 * 1e9 / abs(vmax - vmin))))
10761076
if n_decimals > 9:
10771077
n_decimals = 9
10781078
return self.format_timedelta_ticks(x, pos, n_decimals)

pandas/tests/plotting/test_converter.py

+11
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,14 @@ def test_format_timedelta_ticks(self, x, decimal, format_expected):
372372
tdc = converter.TimeSeries_TimedeltaFormatter
373373
result = tdc.format_timedelta_ticks(x, pos=None, n_decimals=decimal)
374374
assert result == format_expected
375+
376+
@pytest.mark.parametrize("view_interval", [(1, 2), (2, 1)])
377+
def test_call_w_different_view_intervals(self, view_interval, monkeypatch):
378+
# previously broke on reversed xlmits; see GH37454
379+
class mock_axis:
380+
def get_view_interval(self):
381+
return view_interval
382+
383+
tdc = converter.TimeSeries_TimedeltaFormatter()
384+
monkeypatch.setattr(tdc, "axis", mock_axis())
385+
tdc(0.0, 0)

pandas/tests/plotting/test_series.py

+13
Original file line numberDiff line numberDiff line change
@@ -983,3 +983,16 @@ def test_xlabel_ylabel_series(self, kind, index_name, old_label, new_label):
983983
ax = ser.plot(kind=kind, ylabel=new_label, xlabel=new_label)
984984
assert ax.get_ylabel() == new_label
985985
assert ax.get_xlabel() == new_label
986+
987+
@pytest.mark.parametrize(
988+
"index",
989+
[
990+
pd.timedelta_range(start=0, periods=2, freq="D"),
991+
[pd.Timedelta(days=1), pd.Timedelta(days=2)],
992+
],
993+
)
994+
def test_timedelta_index(self, index):
995+
# GH37454
996+
xlims = (3, 1)
997+
ax = Series([1, 2], index=index).plot(xlim=(xlims))
998+
assert ax.get_xlim() == (3, 1)

0 commit comments

Comments
 (0)