Хотите нарисовать эллипсы разных размеров и цветов на легенде matplotlib - PullRequest
0 голосов
/ 07 октября 2019

У меня есть сюжет с ассортиментом эллипсов разного размера / цвета, и я хочу создать для них «общую» легенду, например, «большой красный эллипс означает это, маленький синий эллипс означает, что» и т. Д.

Я следовал примеру с HandlerPatch, который дает мне 75% пути. https://matplotlib.org/3.1.1/tutorials/intermediate/legend_guide.html

Используя приведенный выше пример, я могу получить формы эллипса в легенде и настроить цвет каждого эллипса (задав каждому объекту mpatches.Circle цветовой аргумент). Это 75% ... но все они имеют одинаковую высоту / ширину, и я не знаю, как я могу это контролировать, потому что для объекта mpatches.Circle нет аргумента ширины, а высота / ширина жестко задана"в функцию create_artists для класса HandlerEllipse. Я, наверное, очень близко, но я полностью застрял! Любая помощь высоко ценится.

РЕДАКТИРОВАТЬ ПОЛУЧИЛ ЭТО!

Итак, что я сделал, благодаря предложению Томаса Ланга взглянуть на эту ссылку (https://intoli.com/blog/resizing-matplotlib-legend-markers/), - сделать что-то похожее. Постройте эллипсы на легенде, а затем переберите их и измените их атрибуты. Смотрите код ниже:

'' 'python

#exact same class as matplotlib example:
class HandlerEllipse(HandlerPatch):
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize, trans):
        center = 0.5 * width - 0.5 * xdescent, 0.5 * height - 0.5 * ydescent
        p = mpatches.Ellipse(xy=center, width=width + xdescent,
                             height=height + ydescent)
        self.update_prop(p, orig_handle, legend)
        p.set_transform(trans)
        return [p]

cmap = cm.get_cmap(name='Spectral_r', lut=None)
#plotting a test case "two entry legend", tring to get two differently sized, differently colored ellipses    
c = [mpatches.Circle((),color=cmap(0.1))
     ,mpatches.Circle((),color=cmap(0.9))]
legend = axs[plot].legend(c,['Small Blue','Big Red'], handler_map={mpatches.Circle: HandlerEllipse()})
#here's the 'trick', loop through each legend handle and alter their widths.. using the enumerate function to move along sequentially
for i,legend_handle in enumerate(legend.legendHandles):
    legend_handle.width = (10+i*10)

' ''

1 Ответ

1 голос
/ 07 октября 2019

Вы можете взять размер созданного прокси-исполнителя и передать его в обработчик легенды.

import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerPatch
import matplotlib.patches as mpatches

class HandlerEllipse(HandlerPatch):
    def create_artists(self, legend, orig_handle,
                       xdescent, ydescent, width, height, fontsize, trans):
        center = 0.5 * width - 0.5 * xdescent, 0.5 * height - 0.5 * ydescent
        p = mpatches.Ellipse(xy=center, width=orig_handle.width,
                                        height=orig_handle.height)
        self.update_prop(p, orig_handle, legend)
        p.set_transform(trans)
        return [p]

fig, ax = plt.subplots()
cmap = plt.cm.get_cmap(name='Spectral_r', lut=None)

c = [mpatches.Ellipse((), width=10, height=5, color=cmap(0.1)),
     mpatches.Ellipse((), width=20, height=5, color=cmap(0.9))]
legend = ax.legend(c,['Small Blue','Big Red'], handler_map={mpatches.Ellipse: HandlerEllipse()})

plt.show()

enter image description here

...