matplotlib
Legends
Zoeken…
Simple Legend
Stel dat u meerdere lijnen in dezelfde plot hebt, elk van een andere kleur, en u wilt een legende maken om te vertellen wat elke lijn vertegenwoordigt. U kunt dit doen door een label door te geven aan elk van de regels wanneer u plot()
aanroept. De volgende regel krijgt bijvoorbeeld het label 'Mijn regel 1' .
ax.plot(x, y1, color="red", label="My Line 1")
Dit specificeert de tekst die zal verschijnen in de legenda voor die regel. Om de werkelijke legende zichtbaar te maken, kunnen we ax.legend()
aanroepen
Standaard wordt er een legende in een vak in de rechterbovenhoek van de plot gemaakt. U kunt argumenten doorgeven aan legend()
om het aan te passen. We kunnen het bijvoorbeeld in de rechteronderhoek plaatsen, zonder een kader eromheen en een titel voor de legenda maken door het volgende aan te roepen:
ax.legend(loc="lower right", title="Legend Title", frameon=False)
Hieronder is een voorbeeld:
import matplotlib.pyplot as plt
# The data
x = [1, 2, 3]
y1 = [2, 15, 27]
y2 = [10, 40, 45]
y3 = [5, 25, 40]
# Initialize the figure and axes
fig, ax = plt.subplots(1, figsize=(8, 6))
# Set the title for the figure
fig.suptitle('Simple Legend Example ', fontsize=15)
# Draw all the lines in the same plot, assigning a label for each one to be
# shown in the legend
ax.plot(x, y1, color="red", label="My Line 1")
ax.plot(x, y2, color="green", label="My Line 2")
ax.plot(x, y3, color="blue", label="My Line 3")
# Add a legend with title, position it on the lower right (loc) with no box framing (frameon)
ax.legend(loc="lower right", title="Legend Title", frameon=False)
# Show the plot
plt.show()
Legende buiten plot geplaatst
Soms is het nodig of wenselijk om de legende buiten de plot te plaatsen. De volgende code laat zien hoe het moet.
import matplotlib.pylab as plt
fig, ax = plt.subplots(1, 1, figsize=(10,6)) # make the figure with the size 10 x 6 inches
fig.suptitle('Example of a Legend Being Placed Outside of Plot')
# The data
x = [1, 2, 3]
y1 = [1, 2, 4]
y2 = [2, 4, 8]
y3 = [3, 5, 14]
# Labels to use for each line
line_labels = ["Item A", "Item B", "Item C"]
# Create the lines, assigning different colors for each one.
# Also store the created line objects
l1 = ax.plot(x, y1, color="red")[0]
l2 = ax.plot(x, y2, color="green")[0]
l3 = ax.plot(x, y3, color="blue")[0]
fig.legend([l1, l2, l3], # List of the line objects
labels= line_labels, # The labels for each line
loc="center right", # Position of the legend
borderaxespad=0.1, # Add little spacing around the legend box
title="Legend Title") # Title for the legend
# Adjust the scaling factor to fit your legend text completely outside the plot
# (smaller value results in more space being made for the legend)
plt.subplots_adjust(right=0.85)
plt.show()
Een andere manier om de legende buiten de plot te plaatsen, is door bbox_to_anchor
+ bbox_extra_artists
+ bbox_inches='tight'
, zoals in het onderstaande voorbeeld:
import matplotlib.pyplot as plt
# Data
all_x = [10,20,30]
all_y = [[1,3], [1.5,2.9],[3,2]]
# Plot
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(all_x, all_y)
# Add legend, title and axis labels
lgd = ax.legend([ 'Lag ' + str(lag) for lag in all_x], loc='center right', bbox_to_anchor=(1.3, 0.5))
ax.set_title('Title')
ax.set_xlabel('x label')
ax.set_ylabel('y label')
fig.savefig('image_output.png',
dpi=300,
format='png',
bbox_extra_artists=(lgd,),
bbox_inches='tight')
Enkele legende gedeeld over meerdere subplots
Soms hebt u een raster van subplots en wilt u een enkele legenda die alle lijnen voor elk van de subplots beschrijft, zoals in de volgende afbeelding.
Om dit te doen, moet u een algemene legenda voor de figuur maken in plaats van een legenda op assenniveau te maken (waardoor een afzonderlijke legenda voor elk subplot wordt gemaakt). Dit wordt bereikt door fig.legend()
aan te roepen fig.legend()
zoals te zien is in de code voor de volgende code.
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(10,4))
fig.suptitle('Example of a Single Legend Shared Across Multiple Subplots')
# The data
x = [1, 2, 3]
y1 = [1, 2, 3]
y2 = [3, 1, 3]
y3 = [1, 3, 1]
y4 = [2, 2, 3]
# Labels to use in the legend for each line
line_labels = ["Line A", "Line B", "Line C", "Line D"]
# Create the sub-plots, assigning a different color for each line.
# Also store the line objects created
l1 = ax1.plot(x, y1, color="red")[0]
l2 = ax2.plot(x, y2, color="green")[0]
l3 = ax3.plot(x, y3, color="blue")[0]
l4 = ax3.plot(x, y4, color="orange")[0] # A second line in the third subplot
# Create the legend
fig.legend([l1, l2, l3, l4], # The line objects
labels=line_labels, # The labels for each line
loc="center right", # Position of legend
borderaxespad=0.1, # Small spacing around legend box
title="Legend Title" # Title for the legend
)
# Adjust the scaling factor to fit your legend text completely outside the plot
# (smaller value results in more space being made for the legend)
plt.subplots_adjust(right=0.85)
plt.show()
Iets om op te merken aan het bovenstaande voorbeeld is het volgende:
l1 = ax1.plot(x, y1, color="red")[0]
Wanneer plot()
wordt aangeroepen, wordt een lijst met line2D- objecten geretourneerd . In dit geval retourneert het gewoon een lijst met één enkel line2D- object, dat wordt geëxtraheerd met de indexering [0]
en opgeslagen in l1
.
Een lijst van alle line2D- objecten waarin we geïnteresseerd zijn, moet worden doorgegeven als het eerste argument voor fig.legend()
. Het tweede argument voor fig.legend()
is ook noodzakelijk. Het wordt verondersteld een lijst met tekenreeksen te zijn die worden gebruikt als labels voor elke regel in de legenda.
De andere argumenten die worden doorgegeven aan fig.legend()
zijn puur optioneel en helpen alleen bij het fig.legend()
de esthetiek van de legende.
Meerdere legendes op dezelfde as
Als u plt.legend()
of ax.legend()
meerdere ax.legend()
, wordt de eerste legenda verwijderd en wordt een nieuwe legenda getekend. Volgens de officiële documentatie :
Dit is gedaan zodat het mogelijk is om legend () herhaaldelijk aan te roepen om de legend bij te werken naar de nieuwste grepen op de assen
Wees echter niet bang: het is nog steeds vrij eenvoudig om een tweede legende (of derde of vierde ...) aan een as toe te voegen. In het voorbeeld hier plotten we twee lijnen en plotten vervolgens markeringen op hun respectieve maxima en minima. De ene legende is voor de lijnen en de andere voor de markeringen.
import matplotlib.pyplot as plt
import numpy as np
# Generate data for plotting:
x = np.linspace(0,2*np.pi,100)
y0 = np.sin(x)
y1 = .9*np.sin(.9*x)
# Find their maxima and minima and store
maxes = np.empty((2,2))
mins = np.empty((2,2))
for k,y in enumerate([y0,y1]):
maxloc = y.argmax()
maxes[k] = x[maxloc], y[maxloc]
minloc = y.argmin()
mins[k] = x[minloc], y[minloc]
# Instantiate figure and plot
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y0, label='y0')
ax.plot(x,y1, label='y1')
# Plot maxima and minima, and keep references to the lines
maxline, = ax.plot(maxes[:,0], maxes[:,1], 'r^')
minline, = ax.plot(mins[:,0], mins[:,1], 'ko')
# Add first legend: only labeled data is included
leg1 = ax.legend(loc='lower left')
# Add second legend for the maxes and mins.
# leg1 will be removed from figure
leg2 = ax.legend([maxline,minline],['max','min'], loc='upper right')
# Manually add the first legend back
ax.add_artist(leg1)
De sleutel is om ervoor te zorgen dat u verwijzingen naar de legenda-objecten hebt. De eerste die u instantieert ( leg1
) wordt uit de figuur verwijderd wanneer u de tweede toevoegt, maar het leg1
object bestaat nog steeds en kan weer worden toegevoegd met ax.add_artist
.
Het mooie is dat je beide legendes nog steeds kunt manipuleren. Voeg bijvoorbeeld het volgende toe onderaan de bovenstaande code:
leg1.get_lines()[0].set_lw(8)
leg2.get_texts()[1].set_color('b')
Ten slotte is het vermeldenswaard dat in het voorbeeld alleen de lijnen labels kregen wanneer ze werden geplot, wat betekent dat ax.legend()
alleen die lijnen aan het leg1
. De legenda voor de markeringen ( leg2
) vereiste daarom de lijnen en labels als argumenten toen het werd geïnstantieerd. Als alternatief konden we ook labels aan de markers hebben gegeven wanneer ze werden uitgezet. Maar dan zouden beide aanroepen van ax.legend
wat extra argumenten nodig hebben, zodat elke legende alleen de items bevatte die we wilden.