Skip to content

BUG: Make secondary_y work properly for bar plots GH3598 #4024

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 26, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ pandas 0.11.1
is a ``list`` or ``tuple``.
- Fixed bug where a time-series was being selected in preference to an actual column name
in a frame (:issue:`3594`)
- Make secondary_y work properly for bar plots (:issue:`3598`)
- Fix modulo and integer division on Series,DataFrames to act similary to ``float`` dtypes to return
``np.nan`` or ``np.inf`` as appropriate (:issue:`3590`)
- Fix incorrect dtype on groupby with ``as_index=False`` (:issue:`3610`)
Expand Down
43 changes: 26 additions & 17 deletions pandas/tools/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,11 @@ def _maybe_add_color(self, colors, kwds, style, i):
if has_color and (style is None or re.match('[a-z]+', style) is None):
kwds['color'] = colors[i % len(colors)]

def _get_marked_label(self, label, col_num):
if self.on_right(col_num):
return label + ' (right)'
else:
return label

class KdePlot(MPLPlot):
def __init__(self, data, **kwargs):
Expand Down Expand Up @@ -1214,10 +1219,12 @@ def _make_plot(self):

newline = plotf(*args, **kwds)[0]
lines.append(newline)
leg_label = label
if self.mark_right and self.on_right(i):
leg_label += ' (right)'
labels.append(leg_label)

if self.mark_right:
labels.append(self._get_marked_label(label, i))
else:
labels.append(label)

ax.grid(self.grid)

if self._is_datetype():
Expand All @@ -1235,18 +1242,16 @@ def _make_ts_plot(self, data, **kwargs):
lines = []
labels = []

def to_leg_label(label, i):
if self.mark_right and self.on_right(i):
return label + ' (right)'
return label

def _plot(data, col_num, ax, label, style, **kwds):
newlines = tsplot(data, plotf, ax=ax, label=label,
style=style, **kwds)
ax.grid(self.grid)
lines.append(newlines[0])
leg_label = to_leg_label(label, col_num)
labels.append(leg_label)

if self.mark_right:
labels.append(self._get_marked_label(label, col_num))
else:
labels.append(label)

if isinstance(data, Series):
ax = self._get_ax(0) # self.axes[0]
Expand Down Expand Up @@ -1356,6 +1361,7 @@ class BarPlot(MPLPlot):
_default_rot = {'bar': 90, 'barh': 0}

def __init__(self, data, **kwargs):
self.mark_right = kwargs.pop('mark_right', True)
self.stacked = kwargs.pop('stacked', False)
self.ax_pos = np.arange(len(data)) + 0.25
if self.stacked:
Expand Down Expand Up @@ -1398,15 +1404,14 @@ def _make_plot(self):
rects = []
labels = []

ax = self._get_ax(0) # self.axes[0]

bar_f = self.bar_f

pos_prior = neg_prior = np.zeros(len(self.data))

K = self.nseries

for i, (label, y) in enumerate(self._iter_data()):
ax = self._get_ax(i)
label = com.pprint_thing(label)
kwds = self.kwds.copy()
kwds['color'] = colors[i % len(colors)]
Expand All @@ -1419,8 +1424,6 @@ def _make_plot(self):
start = 0 if mpl.__version__ == "1.2.1" else None

if self.subplots:
ax = self._get_ax(i) # self.axes[i]

rect = bar_f(ax, self.ax_pos, y, self.bar_width,
start = start,
**kwds)
Expand All @@ -1437,7 +1440,10 @@ def _make_plot(self):
start = start,
label=label, **kwds)
rects.append(rect)
labels.append(label)
if self.mark_right:
labels.append(self._get_marked_label(label, i))
else:
labels.append(label)

if self.legend and not self.subplots:
patches = [r[0] for r in rects]
Expand Down Expand Up @@ -1537,7 +1543,10 @@ def plot_frame(frame=None, x=None, y=None, subplots=False, sharex=True,
Rotation for ticks
secondary_y : boolean or sequence, default False
Whether to plot on the secondary y-axis
If dict then can select which columns to plot on secondary y-axis
If a list/tuple, which columns to plot on secondary y-axis
mark_right: boolean, default True
When using a secondary_y axis, should the legend label the axis of
the various columns automatically
kwds : keywords
Options to pass to matplotlib plotting method

Expand Down
22 changes: 22 additions & 0 deletions pandas/tseries/tests/test_plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,16 @@ def test_secondary_frame(self):
self.assert_(axes[1].get_yaxis().get_ticks_position() == 'default')
self.assert_(axes[2].get_yaxis().get_ticks_position() == 'right')

@slow
def test_secondary_bar_frame(self):
import matplotlib.pyplot as plt
plt.close('all')
df = DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c'])
axes = df.plot(kind='bar', secondary_y=['a', 'c'], subplots=True)
self.assert_(axes[0].get_yaxis().get_ticks_position() == 'right')
self.assert_(axes[1].get_yaxis().get_ticks_position() == 'default')
self.assert_(axes[2].get_yaxis().get_ticks_position() == 'right')

@slow
def test_mixed_freq_regular_first(self):
import matplotlib.pyplot as plt
Expand Down Expand Up @@ -864,6 +874,18 @@ def test_secondary_legend(self):
self.assert_(leg.get_texts()[2].get_text() == 'C')
self.assert_(leg.get_texts()[3].get_text() == 'D')

plt.clf()
ax = df.plot(kind='bar', secondary_y=['A'])
leg = ax.get_legend()
self.assert_(leg.get_texts()[0].get_text() == 'A (right)')
self.assert_(leg.get_texts()[1].get_text() == 'B')

plt.clf()
ax = df.plot(kind='bar', secondary_y=['A'], mark_right=False)
leg = ax.get_legend()
self.assert_(leg.get_texts()[0].get_text() == 'A')
self.assert_(leg.get_texts()[1].get_text() == 'B')

plt.clf()
ax = fig.add_subplot(211)
df = tm.makeTimeDataFrame()
Expand Down