Skip to content

Commit dba996f

Browse files
Chang Shewesm
Chang She
authored andcommitted
ENH: secondary y-axis
1 parent 09ba4ce commit dba996f

File tree

2 files changed

+54
-18
lines changed

2 files changed

+54
-18
lines changed

pandas/tools/plotting.py

+41-18
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ def __init__(self, data, kind=None, by=None, subplots=False, sharex=True,
314314
self.fig = fig
315315
self.axes = None
316316

317+
self.secondary_y = kwds.pop('secondary_y', False)
318+
317319
self.kwds = kwds
318320

319321
def _iter_data(self):
@@ -363,18 +365,26 @@ def _setup_subplots(self):
363365
if self.ax is None:
364366
fig, axes = _subplots(nrows=nrows, ncols=ncols,
365367
sharex=self.sharex, sharey=self.sharey,
366-
figsize=self.figsize)
368+
figsize=self.figsize,
369+
secondary_y=self.secondary_y)
367370
else:
368371
fig, axes = _subplots(nrows=nrows, ncols=ncols,
369372
sharex=self.sharex, sharey=self.sharey,
370-
figsize=self.figsize, ax=self.ax)
371-
373+
figsize=self.figsize, ax=self.ax,
374+
secondary_y=self.secondary_y)
372375
else:
373376
if self.ax is None:
374377
fig = self.plt.figure(figsize=self.figsize)
375-
self.ax = fig.add_subplot(111)
378+
ax = fig.add_subplot(111)
379+
if self.secondary_y:
380+
ax = ax.twinx()
381+
self.ax = ax
376382
else:
383+
ax = self.ax
377384
fig = self.ax.get_figure()
385+
if self.secondary_y:
386+
ax = ax.twinx()
387+
self.ax = ax
378388

379389
axes = [self.ax]
380390

@@ -500,6 +510,16 @@ def _get_index_name(self):
500510

501511
return name
502512

513+
def _get_ax_and_style(self, i):
514+
if self.subplots:
515+
ax = self.axes[i]
516+
style = 'k'
517+
else:
518+
style = '' # empty string ignored
519+
ax = self.ax
520+
521+
return ax, style
522+
503523
class KdePlot(MPLPlot):
504524
def __init__(self, data, **kwargs):
505525
MPLPlot.__init__(self, data, **kwargs)
@@ -508,12 +528,9 @@ def _make_plot(self):
508528
from scipy.stats import gaussian_kde
509529
plotf = self._get_plot_function()
510530
for i, (label, y) in enumerate(self._iter_data()):
511-
if self.subplots:
512-
ax = self.axes[i]
513-
style = 'k'
514-
else:
515-
style = '' # empty string ignored
516-
ax = self.ax
531+
532+
ax, style = self._get_ax_and_style(i)
533+
517534
if self.style:
518535
style = self.style
519536
gkde = gaussian_kde(y)
@@ -577,12 +594,9 @@ def _make_plot(self):
577594
plotf = self._get_plot_function()
578595

579596
for i, (label, y) in enumerate(self._iter_data()):
580-
if self.subplots:
581-
ax = self.axes[i]
582-
style = 'k'
583-
else:
584-
style = '' # empty string ignored
585-
ax = self.ax
597+
598+
ax, style = self._get_ax_and_style(i)
599+
586600
if self.style:
587601
style = self.style
588602

@@ -1253,7 +1267,7 @@ def _get_layout(nplots):
12531267
# copied from matplotlib/pyplot.py for compatibility with matplotlib < 1.0
12541268

12551269
def _subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True,
1256-
subplot_kw=None, ax=None, **fig_kw):
1270+
subplot_kw=None, ax=None, secondary_y=False, **fig_kw):
12571271
"""Create a figure with a set of subplots already made.
12581272
12591273
This utility wrapper makes it convenient to create common layouts of
@@ -1295,6 +1309,9 @@ def _subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True,
12951309
12961310
ax : Matplotlib axis object, default None
12971311
1312+
secondary_y : boolean, default False
1313+
If True then y-axis will be on the right
1314+
12981315
Returns:
12991316
13001317
fig, ax : tuple
@@ -1340,6 +1357,9 @@ def _subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True,
13401357

13411358
# Create first subplot separately, so we can share it if requested
13421359
ax0 = fig.add_subplot(nrows, ncols, 1, **subplot_kw)
1360+
if secondary_y:
1361+
ax0 = ax0.twinx()
1362+
13431363
if sharex:
13441364
subplot_kw['sharex'] = ax0
13451365
if sharey:
@@ -1349,7 +1369,10 @@ def _subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True,
13491369
# Note off-by-one counting because add_subplot uses the MATLAB 1-based
13501370
# convention.
13511371
for i in range(1, nplots):
1352-
axarr[i] = fig.add_subplot(nrows, ncols, i+1, **subplot_kw)
1372+
ax = fig.add_subplot(nrows, ncols, i+1, **subplot_kw)
1373+
if secondary_y:
1374+
ax = ax.twinx()
1375+
axarr[i] = ax
13531376

13541377
if nplots > 1:
13551378
if sharex and nrows > 1:

pandas/tseries/tests/test_plotting.py

+13
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,19 @@ def test_finder_monthly(self):
192192
rs = xaxis.get_majorticklocs()[0]
193193
self.assert_(rs == xp)
194194

195+
def test_secondary_y(self):
196+
import matplotlib.pyplot as plt
197+
plt.close('all')
198+
ser = Series(np.random.randn(10))
199+
ax = ser.plot(secondary_y=True)
200+
fig = ax.get_figure()
201+
axes = fig.get_axes()
202+
l = ax.get_lines()[0]
203+
xp = Series(l.get_ydata(), l.get_xdata())
204+
assert_series_equal(ser, xp)
205+
self.assert_(axes[1].get_yaxis().get_ticks_position() == 'right')
206+
207+
195208
PNG_PATH = 'tmp.png'
196209
def _check_plot_works(f, freq=None, series=None, *args, **kwargs):
197210
import matplotlib.pyplot as plt

0 commit comments

Comments
 (0)