简体   繁体   中英

Plot and Scatter legend on subplot

My code looks like this:

pos = 0
x = [1,2,3]
y = [2,3,4]
y2 = [3,5,3]
fig, axs = plt.subplots(1,2)
for pos in [0,1]:
    h1 = axs[pos].scatter(x,y,c='black',label='scttr')
    h2 = axs[pos].plot(x,y2,c='red',label='line')
    axs[pos].legend([h1, h2])
plt.show()

which produces the right legend without text (it shows the object name in the handle). If I try to produce some text for the labels:

pos = 0
x = [1,2,3]
y = [2,3,4]
y2 = [3,5,3]
fig, axs = plt.subplots(1,2)
for pos in [0,1]:
    h1 = axs[pos].scatter(x,y,c='black',label='scttr')
    h2 = axs[pos].plot(x,y2,c='red',label='line')
    axs[pos].legend([h1, h2],['smtng', 'smtng2')
plt.show()

the code crashes with the following:

A proxy artist may be used instead. See: http://matplotlib.org/users/legend_guide.html#using-proxy-artist
"#using-proxy-artist".format(orig_handle))

I did not really understand what proxy artists are and why I would need one for such a basic thing.

The issue is that you can't pass the Line objects directly to the legend call. What you can do, instead, is create some different objects ( known as proxy artists ) to fill the gap, so to speak.

Below are two proxy objects, scatter_proxy and line_proxy , for the scatter plot and line plot, respectively. You create both using matplotlib.lines.Line2D but the one for the scatter plot has a white line (so isn't effectively seen) and has markers added to it. I realise making the line color white is a bit hacky, but it was the best way I could find.

import matplotlib.pyplot as plt
import matplotlib.lines as mlines

pos = 0
x = [1,2,3]
y = [2,3,4]
y2 = [3,5,3]

fig, axs = plt.subplots(1,2)

scatter_color = 'black'
line_color='red'

for pos in [0,1]:
    h1 = axs[pos].scatter(x, y, c=scatter_color, label='scttr')
    h2 = axs[pos].plot(x, y2, c=line_color, label='line')

    scatter_proxy = mlines.Line2D([], [], color='white', marker='o', markerfacecolor=scatter_color)
    line_proxy = mlines.Line2D([], [], color=line_color)

    axs[pos].legend([scatter_proxy, line_proxy],['smtng', 'smtng2'])

plt.show()

在此处输入图片说明

At least in your simple example, it is way simpler if you don't pass any handles to legend :

...
axs[pos].legend()
...

Result:

在此处输入图片说明

You can overwrite the labels like this:

...
axs[pos].legend(['smtng', 'smtng2'])
...

Result: 在此处输入图片说明

If you want to use the handles, you can. However, you have to consider that plot returns a list of Line objects. Thus you have to pass it to legend like this:

...
axs[pos].legend([h1, h2[0]],['smtng', 'smtng2'])
...

You only need to use proxy artists if you want to add something to the legend which does not exist in you plot or if you want (for some reason) make it look different in the legend than in the plot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM