Reputation: 4564
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.
Upvotes: 2
Views: 2849
Reputation: 12701
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.
Upvotes: 1
Reputation: 53678
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()
Upvotes: 2