Tom de Geus
Tom de Geus

Reputation: 5985

One legend entry when plotting several curves using one `plot` call

I am creating a grid by plotting several curves using one plot call as:

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()

x = np.array([[0,1], [0,1], [0,1]])
y = np.array([[0,0], [1,1], [2,2]])

ax.plot([0,1],[0,2], label='foo', color='b')

ax.plot(x.T, y.T, label='bar', color='k')

ax.legend()

plt.show()

The resulting legend has as many 'bar' entries as there are curves (see below). I wish that have only one legend entry per plot call (in this case only one time 'bar').

I want this such that I can have other plot commands (e.g. the one plotting the 'foo' curve) whose curves are automatically included in the legend if they have a label. I specifically want to avoid hand-selecting the handles when constructing the legend, but rather use matplotlib's feature to deal with this by yes/no including a label when plotting. How can I achieve this?

enter image description here

Upvotes: 5

Views: 7704

Answers (3)

Guto Schettini
Guto Schettini

Reputation: 299

Maybe not quite elegant, but the easiest and most straightforward way is to make a second plot using a single pair of elements where you prescribe the 'label' you want!

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()

x = np.array([[0,1], [0,1], [0,1]])
y = np.array([[0,0], [1,1], [2,2]])

ax.plot([0,1],[0,2], label='foo', color='b')

ax.plot(x.T, y.T, color='k')
ax.plot(x[0].T, y[0].T, label='bar', color='k')


ax.legend()

plt.show()

enter image description here

Upvotes: 0

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339705

Here is one possible solution: You may use the fact that underscores do not produce legend entries. So setting all but the first label to "_" suppresses those to appear in the legend.

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()

x = np.array([[0,1], [0,1], [0,1]])
y = np.array([[0,0], [1,1], [2,2]])

ax.plot([0,1],[0,2], label='foo', color='b')

lines = ax.plot(x.T, y.T, label='bar', color='k')
plt.setp(lines[1:], label="_")
ax.legend()

plt.show()

enter image description here

Upvotes: 8

Sheldore
Sheldore

Reputation: 39072

Following is one way using the already existing legend handles and labels. You first get the three handles, labels and then just show the first one. This way additionally gives you a control not only on the order of putting handles but also what to show on the plot.

ax.plot(x.T, y.T,  label='bar', color='k')
handles, labels = ax.get_legend_handles_labels()
ax.legend([handles[0]], [labels[0]], loc='best')

enter image description here

Alternative approach where the legends will only be taken from a particular plot (set of lines) -- ax1 in this case

ax1 = ax.plot(x.T, y.T,  label='bar', color='k')
plt.legend(handles=[ax1[0]], loc='best')

Extending it to you problem with two figures

ax1 = ax.plot([0,1],[0,2], label='foo', color='b')
ax2 = ax.plot(x.T, y.T,  label='bar', color='k')
plt.legend(handles=[ax1[0], ax2[1]], loc='best')

Another alternative using for loops as suggested by @SpghttCd

for i in range(len(x)):
    ax.plot(x[i], y[i], label=('' if i==0 else '_') + 'bar', color='k')

ax.legend()

enter image description here

Upvotes: 5

Related Questions