# Legend transparency, when using secondary axis

The legend of the plot of a secondary axis somehow is transparent to the plot of the other axis. A minimal example to reproduce the problem:

``````import matplotlib.pyplot as plt

ax1 = plt.subplot(111)
ax2 = ax1.twinx()
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r')
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1')
ax1.legend(loc=2)
plt.show()
``````

The output I get is:

As you can see, the legend for the blue plot is overdrawn by the red plot. Rearranging the drawing commands, changing the alpha value or changing the z-orders of the objects doesn’t help.

Is there any way to make the legend opaque to all plots?

EDIT: @`tcaswell`: While your answer works for a single legend, it doesn’t work if both axes have a separate legend. In the following code I added a label for `ax2`:

``````import matplotlib.pyplot as plt
plt.figure()
ax1 = plt.subplot(111)
ax2 = ax1.twinx()
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r', label='ax2')
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1')
ax1.legend(loc=2)
ax2.legend(loc=1)

ax1.set_zorder(1) # make it on top
ax1.set_frame_on(False) # make it transparent
ax2.set_frame_on(True) # make sure there is any background

plt.show()
``````

with the following result:

While your more general approach solves this problem, using `Figure.legend` unfortunately places the legend outside of the plot. Placing them explicitly with `loc` is a bit tedious and doesn’t work well when scaling the plot. Is there a better solution?

You are running into issues because of the way that matplotlib renders the plots. By default the second axes is rendered after the first one (they have the same `zorder` so they render in the order they were added).

To get what you want you just need to tweak a few things about your axes:

``````figure()
ax1 = plt.subplot(111)
ax2 = ax1.twinx()
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r')
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1')
ax1.legend(loc=2)

ax1.set_zorder(1) # make it on top
ax1.set_frame_on(False) # make it transparent
ax2.set_frame_on(True) # make sure there is any background

plt.show()
``````

We set the `zorder` of `ax1` to be higher so it is rendered later, but if we do just that, the second axes isn’t visible at all as it as all drawn under the frame (white background and box) of `ax1`. To fix that we turn the frame off on `ax1` (so we can see `ax2`). However, now we have no background or bounding box at all. We can then turn the frame back on for `ax2`, which gives us the desired effect.

The above method is ad-hoc and not general, if you want to make sure you axes is above all axes, you need to use `Figure.ledgend()`, which is a `figure`, not `axes` feature. Currently, it won’t auto-magically find your labels so you have to pass in the handles and labels explicitly:

``````fig = figure()

ax1 = plt.subplot(111)
ax2 = ax1.twinx()

ln2, = ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r', label='ax2')
ln1, = ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1')

interesting_lines = [ln1, ln2]

fig.legend(*zip(*[(il, il.get_label()) for il in interesting_lines]), loc=2)

plt.show()
``````

Note that this legend is now placed using figure coordinates.