matplotlib
Legendy
Szukaj…
Prosta legenda
Załóżmy, że masz wiele linii na tej samej działce, każda w innym kolorze, i chcesz stworzyć legendę, która powie, co reprezentuje każda linia. Możesz to zrobić, przekazując etykietę do każdego wiersza podczas wywoływania plot()
, np. Następujący wiersz będzie oznaczony „Moja linia 1” .
ax.plot(x, y1, color="red", label="My Line 1")
Określa tekst, który pojawi się w legendzie dla tej linii. Teraz, aby rzeczywista legenda była widoczna, możemy wywołać ax.legend()
Domyślnie utworzy legendę w polu w prawym górnym rogu fabuły. Możesz przekazać argumenty do legend()
aby je dostosować. Na przykład możemy umieścić go w prawym dolnym rogu, bez otaczającego go pola ramki i utworzyć tytuł legendy, wywołując:
ax.legend(loc="lower right", title="Legend Title", frameon=False)
Poniżej znajduje się przykład:
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()
Legenda umieszczona poza fabułą
Czasami konieczne lub pożądane jest umieszczenie legendy poza fabułą. Poniższy kod pokazuje, jak to zrobić.
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()
Innym sposobem na umieszczenie legendy poza fabułą jest użycie bbox_to_anchor
+ bbox_extra_artists
+ bbox_inches='tight'
, jak pokazano w poniższym przykładzie:
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')
Jedna legenda współużytkowana przez wiele podplotów
Czasami masz siatkę podplotów i chcesz mieć jedną legendę, która opisuje wszystkie linie dla każdej podplotów, jak na poniższym obrazku.
Aby to zrobić, musisz utworzyć legendę globalną dla figury zamiast legendy na poziomie osi (która utworzy osobną legendę dla każdego wykresu podrzędnego). Osiąga się to poprzez wywołanie fig.legend()
jak widać w kodzie dla następującego kodu.
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()
Warto zwrócić uwagę na powyższy przykład:
l1 = ax1.plot(x, y1, color="red")[0]
Po wywołaniu funkcji plot()
zwraca listę obiektów line2D . W tym przypadku po prostu zwraca listę z jednym pojedynczym obiektem line2D , który jest wyodrębniany za pomocą indeksowania [0]
i przechowywany w l1
.
Lista wszystkich obiektów line2D , którymi jesteśmy zainteresowani dołączeniem do legendy, musi zostać przekazana jako pierwszy argument do fig.legend()
. fig.legend()
jest również drugi argument do fig.legend()
. Powinna to być lista ciągów znaków, które mają być użyte jako etykiety dla każdej linii w legendzie.
Pozostałe argumenty przekazane do fig.legend()
są czysto opcjonalne i po prostu pomagają w dopracowaniu estetyki legendy.
Wiele legend na tych samych osiach
Jeśli wywołasz plt.legend()
lub ax.legend()
więcej niż jeden raz, pierwsza legenda zostanie usunięta, a nowa zostanie narysowana. Według oficjalnej dokumentacji :
Dokonano tego, aby możliwe było wielokrotne wywoływanie legend () w celu zaktualizowania legendy do najnowszych uchwytów w Osiach
Nie obawiaj się jednak: dodawanie drugiej osi (lub trzeciej lub czwartej ...) do osi jest wciąż dość proste. W tym przykładzie narysujemy dwie linie, a następnie narysujemy znaczniki na odpowiednich maksimach i minimach. Jedna legenda dotyczy linii, a druga znaczników.
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)
Kluczem jest upewnienie się, że masz odniesienia do obiektów legendy. Pierwsza instancja ( leg1
) jest usuwana z figury po dodaniu drugiej, ale obiekt leg1
nadal istnieje i można go dodać z powrotem za pomocą ax.add_artist
.
Naprawdę wspaniałe jest to, że nadal możesz manipulować obiema legendami. Na przykład dodaj następujący kod u dołu powyższego kodu:
leg1.get_lines()[0].set_lw(8)
leg2.get_texts()[1].set_color('b')
Na koniec warto wspomnieć, że w tym przykładzie tylko linie otrzymały etykiety podczas drukowania, co oznacza, że ax.legend()
dodaje tylko te linie do leg1
. W związku z tym legenda znaczników ( leg2
) wymagała wierszy i etykiet jako argumentów podczas tworzenia instancji. Alternatywnie moglibyśmy nadać znaczniki znacznikom, gdy one również zostały narysowane. Ale wtedy oba wywołania ax.legend
wymagałyby dodatkowych argumentów, aby każda legenda zawierała tylko pożądane przez nas przedmioty.