Skip to content

Commit 6d2b34a

Browse files
BUG: mixed freq timeseries plotting with shared axes (GH13341) (#14330)
1 parent 75bb530 commit 6d2b34a

File tree

3 files changed

+64
-9
lines changed

3 files changed

+64
-9
lines changed

doc/source/whatsnew/v0.19.2.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ Bug Fixes
3939

4040
- Bug in ``pd.cut`` with negative values and a single bin (:issue:`14652`)
4141
- Bug in ``pd.to_numeric`` where a 0 was not unsigned on a ``downcast='unsigned'`` argument (:issue:`14401`)
42-
42+
- Bug in plotting regular and irregular timeseries using shared axes
43+
(``sharex=True`` or ``ax.twinx()``) (:issue:`13341`, :issue:`14322`).
4344

4445

4546

pandas/tests/plotting/test_datetimelike.py

+35
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,41 @@ def test_mixed_freq_irreg_period(self):
778778
irreg.plot()
779779
ps.plot()
780780

781+
def test_mixed_freq_shared_ax(self):
782+
783+
# GH13341, using sharex=True
784+
idx1 = date_range('2015-01-01', periods=3, freq='M')
785+
idx2 = idx1[:1].union(idx1[2:])
786+
s1 = Series(range(len(idx1)), idx1)
787+
s2 = Series(range(len(idx2)), idx2)
788+
789+
fig, (ax1, ax2) = self.plt.subplots(nrows=2, sharex=True)
790+
s1.plot(ax=ax1)
791+
s2.plot(ax=ax2)
792+
793+
self.assertEqual(ax1.freq, 'M')
794+
self.assertEqual(ax2.freq, 'M')
795+
self.assertEqual(ax1.lines[0].get_xydata()[0, 0],
796+
ax2.lines[0].get_xydata()[0, 0])
797+
798+
# using twinx
799+
fig, ax1 = self.plt.subplots()
800+
ax2 = ax1.twinx()
801+
s1.plot(ax=ax1)
802+
s2.plot(ax=ax2)
803+
804+
self.assertEqual(ax1.lines[0].get_xydata()[0, 0],
805+
ax2.lines[0].get_xydata()[0, 0])
806+
807+
# TODO (GH14330, GH14322)
808+
# plotting the irregular first does not yet work
809+
# fig, ax1 = plt.subplots()
810+
# ax2 = ax1.twinx()
811+
# s2.plot(ax=ax1)
812+
# s1.plot(ax=ax2)
813+
# self.assertEqual(ax1.lines[0].get_xydata()[0, 0],
814+
# ax2.lines[0].get_xydata()[0, 0])
815+
781816
@slow
782817
def test_to_weekly_resampling(self):
783818
idxh = date_range('1/1/1999', periods=52, freq='W')

pandas/tseries/plotting.py

+27-8
Original file line numberDiff line numberDiff line change
@@ -162,18 +162,37 @@ def _decorate_axes(ax, freq, kwargs):
162162
ax.date_axis_info = None
163163

164164

165-
def _get_freq(ax, series):
166-
# get frequency from data
167-
freq = getattr(series.index, 'freq', None)
168-
if freq is None:
169-
freq = getattr(series.index, 'inferred_freq', None)
170-
165+
def _get_ax_freq(ax):
166+
"""
167+
Get the freq attribute of the ax object if set.
168+
Also checks shared axes (eg when using secondary yaxis, sharex=True
169+
or twinx)
170+
"""
171171
ax_freq = getattr(ax, 'freq', None)
172172
if ax_freq is None:
173+
# check for left/right ax in case of secondary yaxis
173174
if hasattr(ax, 'left_ax'):
174175
ax_freq = getattr(ax.left_ax, 'freq', None)
175176
elif hasattr(ax, 'right_ax'):
176177
ax_freq = getattr(ax.right_ax, 'freq', None)
178+
if ax_freq is None:
179+
# check if a shared ax (sharex/twinx) has already freq set
180+
shared_axes = ax.get_shared_x_axes().get_siblings(ax)
181+
if len(shared_axes) > 1:
182+
for shared_ax in shared_axes:
183+
ax_freq = getattr(shared_ax, 'freq', None)
184+
if ax_freq is not None:
185+
break
186+
return ax_freq
187+
188+
189+
def _get_freq(ax, series):
190+
# get frequency from data
191+
freq = getattr(series.index, 'freq', None)
192+
if freq is None:
193+
freq = getattr(series.index, 'inferred_freq', None)
194+
195+
ax_freq = _get_ax_freq(ax)
177196

178197
# use axes freq if no data freq
179198
if freq is None:
@@ -191,7 +210,7 @@ def _get_freq(ax, series):
191210

192211
def _use_dynamic_x(ax, data):
193212
freq = _get_index_freq(data)
194-
ax_freq = getattr(ax, 'freq', None)
213+
ax_freq = _get_ax_freq(ax)
195214

196215
if freq is None: # convert irregular if axes has freq info
197216
freq = ax_freq
@@ -244,7 +263,7 @@ def _maybe_convert_index(ax, data):
244263
freq = freq.rule_code
245264

246265
if freq is None:
247-
freq = getattr(ax, 'freq', None)
266+
freq = _get_ax_freq(ax)
248267

249268
if freq is None:
250269
raise ValueError('Could not get frequency alias for plotting')

0 commit comments

Comments
 (0)