Skip to content

Commit 0b71b06

Browse files
MarcoGorelliKevin D Smith
authored and
Kevin D Smith
committed
BUG: xticks unnecessarily rotated (pandas-dev#34334)
1 parent 569babb commit 0b71b06

File tree

5 files changed

+49
-8
lines changed

5 files changed

+49
-8
lines changed

doc/source/whatsnew/v1.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ I/O
305305
Plotting
306306
^^^^^^^^
307307

308+
- Bug in :meth:`DataFrame.plot` was rotating xticklabels when ``subplots=True``, even if the x-axis wasn't an irregular time series (:issue:`29460`)
308309
- Bug in :meth:`DataFrame.plot` where a marker letter in the ``style`` keyword sometimes causes a ``ValueError`` (:issue:`21003`)
309310

310311
Groupby/resample/rolling

pandas/plotting/_matplotlib/core.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -1231,11 +1231,15 @@ def get_label(i):
12311231
ax.xaxis.set_major_locator(FixedLocator(xticks))
12321232
ax.set_xticklabels(xticklabels)
12331233

1234+
# If the index is an irregular time series, then by default
1235+
# we rotate the tick labels. The exception is if there are
1236+
# subplots which don't share their x-axes, in which we case
1237+
# we don't rotate the ticklabels as by default the subplots
1238+
# would be too close together.
12341239
condition = (
12351240
not self._use_dynamic_x()
1236-
and data.index.is_all_dates
1237-
and not self.subplots
1238-
or (self.subplots and self.sharex)
1241+
and (data.index.is_all_dates and self.use_index)
1242+
and (not self.subplots or (self.subplots and self.sharex))
12391243
)
12401244

12411245
index_name = self._get_index_name()

pandas/tests/plotting/test_datetimelike.py

+27-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pandas._libs.tslibs import BaseOffset, to_offset
1010
import pandas.util._test_decorators as td
1111

12-
from pandas import DataFrame, Index, NaT, Series, isna
12+
from pandas import DataFrame, Index, NaT, Series, isna, to_datetime
1313
import pandas._testing as tm
1414
from pandas.core.indexes.datetimes import DatetimeIndex, bdate_range, date_range
1515
from pandas.core.indexes.period import Period, PeriodIndex, period_range
@@ -1494,6 +1494,32 @@ def test_matplotlib_scatter_datetime64(self):
14941494
expected = "2017-12-12"
14951495
assert label.get_text() == expected
14961496

1497+
def test_check_xticks_rot(self):
1498+
# https://github.com/pandas-dev/pandas/issues/29460
1499+
# regular time series
1500+
x = to_datetime(["2020-05-01", "2020-05-02", "2020-05-03"])
1501+
df = DataFrame({"x": x, "y": [1, 2, 3]})
1502+
axes = df.plot(x="x", y="y")
1503+
self._check_ticks_props(axes, xrot=0)
1504+
1505+
# irregular time series
1506+
x = to_datetime(["2020-05-01", "2020-05-02", "2020-05-04"])
1507+
df = DataFrame({"x": x, "y": [1, 2, 3]})
1508+
axes = df.plot(x="x", y="y")
1509+
self._check_ticks_props(axes, xrot=30)
1510+
1511+
# use timeseries index or not
1512+
axes = df.set_index("x").plot(y="y", use_index=True)
1513+
self._check_ticks_props(axes, xrot=30)
1514+
axes = df.set_index("x").plot(y="y", use_index=False)
1515+
self._check_ticks_props(axes, xrot=0)
1516+
1517+
# separate subplots
1518+
axes = df.plot(x="x", y="y", subplots=True, sharex=True)
1519+
self._check_ticks_props(axes, xrot=30)
1520+
axes = df.plot(x="x", y="y", subplots=True, sharex=False)
1521+
self._check_ticks_props(axes, xrot=0)
1522+
14971523

14981524
def _check_plot_works(f, freq=None, series=None, *args, **kwargs):
14991525
import matplotlib.pyplot as plt

pandas/tests/plotting/test_frame.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ def _assert_xtickslabels_visibility(self, axes, expected):
4848
for ax, exp in zip(axes, expected):
4949
self._check_visible(ax.get_xticklabels(), visible=exp)
5050

51-
@pytest.mark.xfail(reason="Waiting for PR 34334", strict=True)
5251
@pytest.mark.slow
5352
def test_plot(self):
5453
from pandas.plotting._matplotlib.compat import mpl_ge_3_1_0
@@ -66,6 +65,7 @@ def test_plot(self):
6665

6766
with tm.assert_produces_warning(UserWarning):
6867
axes = _check_plot_works(df.plot, subplots=True, use_index=False)
68+
self._check_ticks_props(axes, xrot=0)
6969
self._check_axes_shape(axes, axes_num=4, layout=(4, 1))
7070

7171
df = DataFrame({"x": [1, 2], "y": [3, 4]})
@@ -78,7 +78,8 @@ def test_plot(self):
7878

7979
df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10]))
8080

81-
_check_plot_works(df.plot, use_index=True)
81+
ax = _check_plot_works(df.plot, use_index=True)
82+
self._check_ticks_props(ax, xrot=0)
8283
_check_plot_works(df.plot, sort_columns=False)
8384
_check_plot_works(df.plot, yticks=[1, 5, 10])
8485
_check_plot_works(df.plot, xticks=[1, 5, 10])
@@ -110,7 +111,8 @@ def test_plot(self):
110111

111112
tuples = zip(string.ascii_letters[:10], range(10))
112113
df = DataFrame(np.random.rand(10, 3), index=MultiIndex.from_tuples(tuples))
113-
_check_plot_works(df.plot, use_index=True)
114+
ax = _check_plot_works(df.plot, use_index=True)
115+
self._check_ticks_props(ax, xrot=0)
114116

115117
# unicode
116118
index = MultiIndex.from_tuples(
@@ -304,12 +306,14 @@ def test_xcompat(self):
304306
ax = df.plot(x_compat=True)
305307
lines = ax.get_lines()
306308
assert not isinstance(lines[0].get_xdata(), PeriodIndex)
309+
self._check_ticks_props(ax, xrot=30)
307310

308311
tm.close()
309312
pd.plotting.plot_params["xaxis.compat"] = True
310313
ax = df.plot()
311314
lines = ax.get_lines()
312315
assert not isinstance(lines[0].get_xdata(), PeriodIndex)
316+
self._check_ticks_props(ax, xrot=30)
313317

314318
tm.close()
315319
pd.plotting.plot_params["x_compat"] = False
@@ -325,12 +329,14 @@ def test_xcompat(self):
325329
ax = df.plot()
326330
lines = ax.get_lines()
327331
assert not isinstance(lines[0].get_xdata(), PeriodIndex)
332+
self._check_ticks_props(ax, xrot=30)
328333

329334
tm.close()
330335
ax = df.plot()
331336
lines = ax.get_lines()
332337
assert not isinstance(lines[0].get_xdata(), PeriodIndex)
333338
assert isinstance(PeriodIndex(lines[0].get_xdata()), PeriodIndex)
339+
self._check_ticks_props(ax, xrot=0)
334340

335341
def test_period_compat(self):
336342
# GH 9012
@@ -486,7 +492,6 @@ def test_groupby_boxplot_sharex(self):
486492
expected = [False, False, True, True]
487493
self._assert_xtickslabels_visibility(axes, expected)
488494

489-
@pytest.mark.xfail(reason="Waiting for PR 34334", strict=True)
490495
@pytest.mark.slow
491496
def test_subplots_timeseries(self):
492497
idx = date_range(start="2014-07-01", freq="M", periods=10)

pandas/tests/plotting/test_series.py

+5
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def test_ts_area_lim(self):
109109
line = ax.get_lines()[0].get_data(orig=False)[0]
110110
assert xmin <= line[0]
111111
assert xmax >= line[-1]
112+
self._check_ticks_props(ax, xrot=0)
112113
tm.close()
113114

114115
# GH 7471
@@ -118,6 +119,7 @@ def test_ts_area_lim(self):
118119
line = ax.get_lines()[0].get_data(orig=False)[0]
119120
assert xmin <= line[0]
120121
assert xmax >= line[-1]
122+
self._check_ticks_props(ax, xrot=30)
121123
tm.close()
122124

123125
tz_ts = self.ts.copy()
@@ -128,6 +130,7 @@ def test_ts_area_lim(self):
128130
line = ax.get_lines()[0].get_data(orig=False)[0]
129131
assert xmin <= line[0]
130132
assert xmax >= line[-1]
133+
self._check_ticks_props(ax, xrot=0)
131134
tm.close()
132135

133136
_, ax = self.plt.subplots()
@@ -136,6 +139,7 @@ def test_ts_area_lim(self):
136139
line = ax.get_lines()[0].get_data(orig=False)[0]
137140
assert xmin <= line[0]
138141
assert xmax >= line[-1]
142+
self._check_ticks_props(ax, xrot=0)
139143

140144
def test_label(self):
141145
s = Series([1, 2])
@@ -284,6 +288,7 @@ def test_irregular_datetime(self):
284288
xp = DatetimeConverter.convert(datetime(1999, 1, 1), "", ax)
285289
ax.set_xlim("1/1/1999", "1/1/2001")
286290
assert xp == ax.get_xlim()[0]
291+
self._check_ticks_props(ax, xrot=30)
287292

288293
def test_unsorted_index_xlim(self):
289294
ser = Series(

0 commit comments

Comments
 (0)