69 votes

augmenter la largeur des lignes de légende dans matplotlib

Je sais que si je modifie la largeur d'une ligne, celle-ci est automatiquement mise à jour dans la légende. Cependant, j'aimerais modifier la largeur de la ligne de la légende sans affecter le tracé.

83voto

Brendan Wood Points 2481

Voici un exemple simple de la manière de procéder :

import numpy as np
import matplotlib.pyplot as plt

# make some data
x = np.linspace(0, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)

# plot sin(x) and cos(x)
p1 = plt.plot(x, y1, 'b-', linewidth=1.0)
p2 = plt.plot(x, y2, 'r-', linewidth=1.0)

# make a legend for both plots
leg = plt.legend([p1, p2], ['sin(x)', 'cos(x)'], loc=1)

# set the linewidth of each legend object
for legobj in leg.legendHandles:
    legobj.set_linewidth(2.0)

plt.show()

32voto

jdhao Points 3136

La méthode de @Brendan Wood utilise l'api fournie par pyplot . Dans matplotlib, la fonction le style orienté objet utilisant des axes est préférable . Voici comment vous pouvez y parvenir en utilisant axes méthode.

import numpy as np
import matplotlib.pyplot as plt

# make some data
x = np.linspace(0, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)

fig, ax = plt.subplots()
ax.plot(x, y1, linewidth=1.0, label='sin(x)')
ax.plot(x, y2, linewidth=1.0, label='cos(x)')

# get the legend object
leg = ax.legend()

# change the line width for the legend
for line in leg.get_lines():
    line.set_linewidth(4.0)

plt.show()

Le graphique produit est présenté ci-dessous, enter image description here

6voto

Par défaut, la légende contient les lignes elles-mêmes. Par conséquent, si l'on modifie la largeur des lignes dans le canevas, les lignes de la légende seront également modifiées (et vice versa, puisqu'il s'agit essentiellement du même objet).

Une solution possible consiste à utiliser une copie de l'artiste de la toile et à ne modifier que la largeur de ligne de la copie.

import numpy as np
import matplotlib.pyplot as plt
import copy

x = np.linspace(0, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
fig = plt.figure()
ax  = fig.add_subplot(111)
ax.plot(x, y1, c='b', label='y1',linewidth=1.0)
ax.plot(x, y2, c='r', label='y2')

# obtain the handles and labels from the figure
handles, labels = ax.get_legend_handles_labels()
# copy the handles
handles = [copy.copy(ha) for ha in handles ]
# set the linewidths to the copies
[ha.set_linewidth(7) for ha in handles ]
# put the copies into the legend
leg = plt.legend(handles=handles, labels=labels)

plt.savefig('leg_example')
plt.show()

enter image description here

Une autre option consisterait à utiliser un handler_map et une fonction de mise à jour. Il s'agit en quelque sorte d'un automatisme : en spécifiant la carte du gestionnaire, toute ligne de la légende devient automatiquement large de 7 points.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerLine2D

x = np.linspace(0, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)
fig = plt.figure()
ax  = fig.add_subplot(111)
ax.plot(x, y1, c='b', label='y1',linewidth=1.0)
ax.plot(x, y2, c='r', label='y2')

linewidth=7
def update(handle, orig):
    handle.update_from(orig)
    handle.set_linewidth(7)

plt.legend(handler_map={plt.Line2D : HandlerLine2D(update_func=update)})

plt.show()

Le résultat est le même que ci-dessus.

4voto

David Zwicker Points 4319

Si vous souhaitez modifier toutes les lignes d'un graphique, il peut être utile de définir votre propre gestionnaire de légende :

import matplotlib.pyplot as plt
from matplotlib import legend_handler
from matplotlib.lines import Line2D
import numpy as np

class MyHandlerLine2D(legend_handler.HandlerLine2D):
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize,
                       trans):

        xdata, xdata_marker = self.get_xdata(legend, xdescent, ydescent,
                                             width, height, fontsize)

        ydata = ((height-ydescent)/2.)*np.ones(xdata.shape, float)
        legline = Line2D(xdata, ydata)

        self.update_prop(legline, orig_handle, legend)
        #legline.update_from(orig_handle)
        #legend._set_artist_props(legline) # after update
        #legline.set_clip_box(None)
        #legline.set_clip_path(None)
        legline.set_drawstyle('default')
        legline.set_marker("")
        legline.set_linewidth(10)

        legline_marker = Line2D(xdata_marker, ydata[:len(xdata_marker)])
        self.update_prop(legline_marker, orig_handle, legend)
        #legline_marker.update_from(orig_handle)
        #legend._set_artist_props(legline_marker)
        #legline_marker.set_clip_box(None)
        #legline_marker.set_clip_path(None)
        legline_marker.set_linestyle('None')
        if legend.markerscale != 1:
            newsz = legline_marker.get_markersize()*legend.markerscale
            legline_marker.set_markersize(newsz)
        # we don't want to add this to the return list because
        # the texts and handles are assumed to be in one-to-one
        # correpondence.
        legline._legmarker = legline_marker

        return [legline, legline_marker]

plt.plot( [0, 1], [0, 1], '-r', lw=1, label='Line' )
plt.legend(handler_map={Line2D:MyHandlerLine2D()})

plt.show()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X