Legend transparency using a secondary axis

The legend about the graph of the secondary axis is somehow transparent for the graph of the other axis. 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: Faulty plot

As you can see, the legend of the blue plot is crossed out with a red plot. Changing the drawing commands, changing the alpha value, or changing the z-orders of objects does not help.

Is there a way to make the legend opaque for all graphs?

EDIT: @ tcaswell : while your answer works for one legend, it does not 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:

Faulty plot with two legends

While your more general approach solves this problem, using Figure.legend unfortunately puts the legend outside the plot. Placing them explicitly with loc bit tedious and does not work when scaling the graph. Is there a better solution?

+6
source share
2 answers

You are having problems due to the way matplotlib displays graphs. By default, the second axis is displayed after the first (they have the same zorder so that they appear in the order in which they were added).

To get what you need, you just need to set up 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 above, so it is displayed later, but if we do just that, then the second axes are not visible at all, since they are all drawn under the frame (white background and field) of ax1 . To fix this, we turn off the frame on ax1 (so that we can see ax2 ). However, now we have no background or bounding box. Then we can turn on the frame for ax2 , which gives us the desired effect.

The above method is ad-hoc and is not general, if you want to make sure that the axes are above all the axes, you need to use Figure.ledgend() , which is figure , not axes . Currently, it will not automatically type shortcuts, so you must explicitly pass them in pens and shortcuts:

 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() 

Notice that this legend is now placed using the shape coordinates.

+8
source

I used bbox_to_anchor to set the location of both legends, and they appeared on top. I don’t know why, but it worked. eg:

 ax1.legend(bbox_to_anchor=(0.16,0.2)) ax2.legend(bbox_to_anchor=(1,0.2)) 
0
source

Source: https://habr.com/ru/post/947510/


All Articles