Skip to content

Commit 87e7e27

Browse files
committed
Merge pull request #7322 from rosnfeld/xlim_issues
BUG: xlim on plots with shared axes (GH2960, GH3490)
2 parents 1e8d5b2 + 12f53c1 commit 87e7e27

File tree

4 files changed

+101
-2
lines changed

4 files changed

+101
-2
lines changed

doc/source/v0.14.1.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ Bug Fixes
271271
- Bug in non-monotonic ``Index.union`` may preserve ``name`` incorrectly (:issue:`7458`)
272272
- Bug in ``DatetimeIndex.intersection`` doesn't preserve timezone (:issue:`4690`)
273273

274+
- Bug with last plotted timeseries dictating ``xlim`` (:issue:`2960`)
275+
- Bug with ``secondary_y`` axis not being considered for timeseries ``xlim`` (:issue:`3490`)
276+
274277
- Bug in ``Float64Index`` assignment with a non scalar indexer (:issue:`7586`)
275278
- Bug in ``pandas.core.strings.str_contains`` does not properly match in a case insensitive fashion when ``regex=False`` and ``case=False`` (:issue:`7505`)
276279

pandas/tools/plotting.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,6 +1563,8 @@ def _make_plot(self):
15631563
kwds = self.kwds.copy()
15641564
self._maybe_add_color(colors, kwds, style, i)
15651565

1566+
lines += _get_all_lines(ax)
1567+
15661568
errors = self._get_errorbars(label=label, index=i)
15671569
kwds = dict(kwds, **errors)
15681570

@@ -3064,6 +3066,20 @@ def _flatten(axes):
30643066
return axes
30653067

30663068

3069+
def _get_all_lines(ax):
3070+
lines = ax.get_lines()
3071+
3072+
# check for right_ax, which can oddly sometimes point back to ax
3073+
if hasattr(ax, 'right_ax') and ax.right_ax != ax:
3074+
lines += ax.right_ax.get_lines()
3075+
3076+
# no such risk with left_ax
3077+
if hasattr(ax, 'left_ax'):
3078+
lines += ax.left_ax.get_lines()
3079+
3080+
return lines
3081+
3082+
30673083
def _get_xlim(lines):
30683084
left, right = np.inf, -np.inf
30693085
for l in lines:

pandas/tseries/plotting.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
from pandas.tseries.converter import (PeriodConverter, TimeSeries_DateLocator,
2323
TimeSeries_DateFormatter)
2424

25+
from pandas.tools.plotting import _get_all_lines
26+
2527
#----------------------------------------------------------------------
2628
# Plotting functions and monkey patches
2729

@@ -78,7 +80,7 @@ def tsplot(series, plotf, **kwargs):
7880

7981
# set date formatter, locators and rescale limits
8082
format_dateaxis(ax, ax.freq)
81-
left, right = _get_xlim(ax.get_lines())
83+
left, right = _get_xlim(_get_all_lines(ax))
8284
ax.set_xlim(left, right)
8385

8486
# x and y coord info
@@ -115,7 +117,7 @@ def _get_ax_freq(ax):
115117
if ax_freq is None:
116118
if hasattr(ax, 'left_ax'):
117119
ax_freq = getattr(ax.left_ax, 'freq', None)
118-
if hasattr(ax, 'right_ax'):
120+
elif hasattr(ax, 'right_ax'):
119121
ax_freq = getattr(ax.right_ax, 'freq', None)
120122
return ax_freq
121123

pandas/tseries/tests/test_plotting.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,84 @@ def test_mpl_nopandas(self):
919919
assert_array_equal(np.array([x.toordinal() for x in dates]),
920920
line2.get_xydata()[:, 0])
921921

922+
@slow
923+
def test_irregular_ts_shared_ax_xlim(self):
924+
# GH 2960
925+
ts = tm.makeTimeSeries()[:20]
926+
ts_irregular = ts[[1, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 17, 18]]
927+
928+
# plot the left section of the irregular series, then the right section
929+
ax = ts_irregular[:5].plot()
930+
ts_irregular[5:].plot(ax=ax)
931+
932+
# check that axis limits are correct
933+
left, right = ax.get_xlim()
934+
self.assertEqual(left, ts_irregular.index.min().toordinal())
935+
self.assertEqual(right, ts_irregular.index.max().toordinal())
936+
937+
@slow
938+
def test_secondary_y_non_ts_xlim(self):
939+
# GH 3490 - non-timeseries with secondary y
940+
index_1 = [1, 2, 3, 4]
941+
index_2 = [5, 6, 7, 8]
942+
s1 = Series(1, index=index_1)
943+
s2 = Series(2, index=index_2)
944+
945+
ax = s1.plot()
946+
left_before, right_before = ax.get_xlim()
947+
s2.plot(secondary_y=True, ax=ax)
948+
left_after, right_after = ax.get_xlim()
949+
950+
self.assertEqual(left_before, left_after)
951+
self.assertLess(right_before, right_after)
952+
953+
@slow
954+
def test_secondary_y_regular_ts_xlim(self):
955+
# GH 3490 - regular-timeseries with secondary y
956+
index_1 = date_range(start='2000-01-01', periods=4, freq='D')
957+
index_2 = date_range(start='2000-01-05', periods=4, freq='D')
958+
s1 = Series(1, index=index_1)
959+
s2 = Series(2, index=index_2)
960+
961+
ax = s1.plot()
962+
left_before, right_before = ax.get_xlim()
963+
s2.plot(secondary_y=True, ax=ax)
964+
left_after, right_after = ax.get_xlim()
965+
966+
self.assertEqual(left_before, left_after)
967+
self.assertLess(right_before, right_after)
968+
969+
@slow
970+
def test_secondary_y_mixed_freq_ts_xlim(self):
971+
# GH 3490 - mixed frequency timeseries with secondary y
972+
rng = date_range('2000-01-01', periods=10000, freq='min')
973+
ts = Series(1, index=rng)
974+
975+
ax = ts.plot()
976+
left_before, right_before = ax.get_xlim()
977+
ts.resample('D').plot(secondary_y=True, ax=ax)
978+
left_after, right_after = ax.get_xlim()
979+
980+
# a downsample should not have changed either limit
981+
self.assertEqual(left_before, left_after)
982+
self.assertEqual(right_before, right_after)
983+
984+
@slow
985+
def test_secondary_y_irregular_ts_xlim(self):
986+
# GH 3490 - irregular-timeseries with secondary y
987+
ts = tm.makeTimeSeries()[:20]
988+
ts_irregular = ts[[1, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 17, 18]]
989+
990+
ax = ts_irregular[:5].plot()
991+
# plot higher-x values on secondary axis
992+
ts_irregular[5:].plot(secondary_y=True, ax=ax)
993+
# ensure secondary limits aren't overwritten by plot on primary
994+
ts_irregular[:5].plot(ax=ax)
995+
996+
left, right = ax.get_xlim()
997+
self.assertEqual(left, ts_irregular.index.min().toordinal())
998+
self.assertEqual(right, ts_irregular.index.max().toordinal())
999+
9221000

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

0 commit comments

Comments
 (0)