увеличить ширину линий легенды в matplotlib

python matplotlib legend

25307 просмотра

4 ответа

4726 Репутация автора

Я знаю, что если я изменю ширину линии, это автоматически обновляется в легенде. Однако я хотел бы просто изменить ширину линии легенды, не затрагивая сюжет.

Автор: Andrea Zonca Источник Размещён: 14.03.2012 05:20

Ответы (4)


62 плюса

5112 Репутация автора

Решение

Вот простой пример того, как это сделать:

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()
Автор: Brendan Wood Размещён: 14.03.2012 05:44

3 плюса

16745 Репутация автора

Если вы хотите изменить все линии на графике, может быть полезно определить собственный обработчик легенды:

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()
Автор: David Zwicker Размещён: 14.03.2012 05:45

6 плюса

6398 Репутация автора

Метод @Brendan Wood использует API, предоставленный pyplot. В matplotlib предпочтительным является объектно-ориентированный стиль с использованием осей . Ниже описано, как вы можете достичь этого, используя axesметод.

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)')
leg = ax.legend()

for line in leg.get_lines():
    line.set_linewidth(4.0)

plt.show()

Произведенный участок показан ниже, введите описание изображения здесь

Автор: jdhao Размещён: 17.01.2018 08:49

3 плюса

174740 Репутация автора

По умолчанию легенда содержит сами строки. Поэтому изменение ширины линий на холсте также приведет к изменению линий в легенде (и наоборот, поскольку они по сути являются одним и тем же объектом).

Возможное решение - использовать копию художника с холста и изменять только ширину линии копии.

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()

введите описание изображения здесь

Другой вариант - использовать функцию handler_mapобновления и. Это как-то автоматически, указание карты обработчика автоматически сделает любую строку в легенде шириной 7 точек.

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()

Результат такой же, как указано выше.

Автор: ImportanceOfBeingErnest Размещён: 17.01.2018 07:43
Вопросы из категории :
32x32