Skip to content

Commit 7629a18

Browse files
JoElfnerTomAugspurger
authored andcommitted
BUG: Enable plotting with PeriodIndex with arbitrary frequencies, resolves #14763 (#26241)
* BUG: Enable plotting with PeriodIndex with arbitrary frequencies, resolves #14763
1 parent 7f0a743 commit 7629a18

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

doc/source/whatsnew/v0.25.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ Plotting
474474
- Fixed bug where :class:`api.extensions.ExtensionArray` could not be used in matplotlib plotting (:issue:`25587`)
475475
- Bug in an error message in :meth:`DataFrame.plot`. Improved the error message if non-numerics are passed to :meth:`DataFrame.plot` (:issue:`25481`)
476476
- Bug in incorrect ticklabel positions when plotting an index that are non-numeric / non-datetime (:issue:`7612` :issue:`15912` :issue:`22334`)
477+
- Fixed bug causing plots of :class:`PeriodIndex` timeseries to fail if the frequency is a multiple of the frequency rule code (:issue:`14763`)
478+
-
477479
-
478480
-
479481

pandas/plotting/_timeseries.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def _get_index_freq(data):
262262
def _maybe_convert_index(ax, data):
263263
# tsplot converts automatically, but don't want to convert index
264264
# over and over for DataFrames
265-
if isinstance(data.index, ABCDatetimeIndex):
265+
if isinstance(data.index, (ABCDatetimeIndex, ABCPeriodIndex)):
266266
freq = getattr(data.index, 'freq', None)
267267

268268
if freq is None:
@@ -279,7 +279,10 @@ def _maybe_convert_index(ax, data):
279279
freq = get_base_alias(freq)
280280
freq = frequencies.get_period_alias(freq)
281281

282-
data = data.to_period(freq=freq)
282+
if isinstance(data.index, ABCDatetimeIndex):
283+
data = data.to_period(freq=freq)
284+
elif isinstance(data.index, ABCPeriodIndex):
285+
data.index = data.index.asfreq(freq=freq)
283286
return data
284287

285288

pandas/tests/plotting/test_datetimelike.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ class TestTSPlot(TestPlotBase):
2626
def setup_method(self, method):
2727
TestPlotBase.setup_method(self, method)
2828

29-
freq = ['S', 'T', 'H', 'D', 'W', 'M', 'Q', 'A']
30-
idx = [period_range('12/31/1999', freq=x, periods=100) for x in freq]
29+
self.freq = ['S', 'T', 'H', 'D', 'W', 'M', 'Q', 'A']
30+
idx = [
31+
period_range('12/31/1999', freq=x, periods=100) for x in self.freq]
3132
self.period_ser = [Series(np.random.randn(len(x)), x) for x in idx]
3233
self.period_df = [DataFrame(np.random.randn(len(x), 3), index=x,
3334
columns=['A', 'B', 'C'])
@@ -209,6 +210,16 @@ def test_line_plot_period_series(self):
209210
for s in self.period_ser:
210211
_check_plot_works(s.plot, s.index.freq)
211212

213+
@pytest.mark.slow
214+
@pytest.mark.parametrize(
215+
'frqncy', ['1S', '3S', '5T', '7H', '4D', '8W', '11M', '3A'])
216+
def test_line_plot_period_mlt_series(self, frqncy):
217+
# test period index line plot for series with multiples (`mlt`) of the
218+
# frequency (`frqncy`) rule code. tests resolution of issue #14763
219+
idx = period_range('12/31/1999', freq=frqncy, periods=100)
220+
s = Series(np.random.randn(len(idx)), idx)
221+
_check_plot_works(s.plot, s.index.freq.rule_code)
222+
212223
@pytest.mark.slow
213224
def test_line_plot_datetime_series(self):
214225
for s in self.datetime_ser:
@@ -219,6 +230,19 @@ def test_line_plot_period_frame(self):
219230
for df in self.period_df:
220231
_check_plot_works(df.plot, df.index.freq)
221232

233+
@pytest.mark.slow
234+
@pytest.mark.parametrize(
235+
'frqncy', ['1S', '3S', '5T', '7H', '4D', '8W', '11M', '3A'])
236+
def test_line_plot_period_mlt_frame(self, frqncy):
237+
# test period index line plot for DataFrames with multiples (`mlt`)
238+
# of the frequency (`frqncy`) rule code. tests resolution of issue
239+
# #14763
240+
idx = period_range('12/31/1999', freq=frqncy, periods=100)
241+
df = DataFrame(np.random.randn(len(idx), 3), index=idx,
242+
columns=['A', 'B', 'C'])
243+
freq = df.index.asfreq(df.index.freq.rule_code).freq
244+
_check_plot_works(df.plot, freq)
245+
222246
@pytest.mark.slow
223247
def test_line_plot_datetime_frame(self):
224248
for df in self.datetime_df:

0 commit comments

Comments
 (0)