Как изменить легенду matplotlib после ее создания?

у меня есть доступ к экземпляру figure fig = pylab.gcf(). Я знаю, что на этом рисунке есть легенда, и я могу получить к ней доступ через myLegend = fig.gca().legend_. Теперь я хочу изменить свойства легенды. Некоторые из них у меня есть доступ через сеттеры, такие как myLegend.set_frame_on(True).

при создании легенды она принимает ряд аргументов ключевого слова:

класс библиотек matplotlib.легенда.Легенда (родитель, дескрипторы, метки, loc=нет, numpoints=нет, markerscale=нет, scatterpoints=нет, scatteryoffsets=нет, prop=нет, fontsize=нет, borderpad=нет, labelspacing=нет, handlelength=нет, handleheight=нет, handletextpad=нет, borderaxespad=нет, свойства columnspacing=нет, номер колонки=1, mode=нет, fancybox=нет, shadow=нет, title=нет, framealpha=нет, bbox_to_anchor=нет, bbox_transform=нет, frameon=нет, handler_map=нет)

как я могу изменить все аргументы ключевого слова в легенде после легенда?

один из проблемные из них numpoints (количество маркеров в легенде, по умолчанию-2). Ниже приведен пример того, как я хочу его изменить:

это показывает, как я хочу, чтобы программы

import pylab
pylab.plot(0,0,'ro', label = 'one point')
pylab.legend(loc = "lower left")
# no modifications above this line
setattr(pylab.gcf().gca().legend_, 'numpoints',1)
pylab.show()

это показывает, как я хочу, чтобы это выглядело как

import pylab
pylab.plot(0,0,'ro', label = 'one point')
pylab.legend(numpoints = 1, loc = "lower left")
pylab.show()

Я проверил исходный код, есть переменная numpoint, которая изменяется, но верхний регистр не обновляется до экрана. Что я упускаю?

4 ответов


я написал функцию modify_legend который изменяет легенду после ее создания. Он в основном считывает все параметры из уже созданной легенды, обновляет ее с параметрами ключа-значения, которые вы предоставили, и вызывает legend(...) опять со всеми возможными параметрами.

ваша проблема будет решена с:
import pylab
pylab.plot(0,0,'ro', label = 'one point')
pylab.legend(loc = "lower left")

modify_legend(numpoints = 1)

pylab.show()

здесь код modify_legend:

def modify_legend(**kwargs):
    import matplotlib as mpl

    l = mpl.pyplot.gca().legend_

    defaults = dict(
        loc = l._loc,
        numpoints = l.numpoints,
        markerscale = l.markerscale,
        scatterpoints = l.scatterpoints,
        scatteryoffsets = l._scatteryoffsets,
        prop = l.prop,
        # fontsize = None,
        borderpad = l.borderpad,
        labelspacing = l.labelspacing,
        handlelength = l.handlelength,
        handleheight = l.handleheight,
        handletextpad = l.handletextpad,
        borderaxespad = l.borderaxespad,
        columnspacing = l.columnspacing,
        ncol = l._ncol,
        mode = l._mode,
        fancybox = type(l.legendPatch.get_boxstyle())==mpl.patches.BoxStyle.Round,
        shadow = l.shadow,
        title = l.get_title().get_text() if l._legend_title_box.get_visible() else None,
        framealpha = l.get_frame().get_alpha(),
        bbox_to_anchor = l.get_bbox_to_anchor()._bbox,
        bbox_transform = l.get_bbox_to_anchor()._transform,
        frameon = l._drawFrame,
        handler_map = l._custom_handler_map,
    )

    if "fontsize" in kwargs and "prop" not in kwargs:
        defaults["prop"].set_size(kwargs["fontsize"])

    mpl.pyplot.legend(**dict(defaults.items() + kwargs.items()))

примечания по коду:

  • некоторые параметры могли легко Читайте из

Вы можете использовать команду pylab.legend снова с правильными ключевыми словами / аргументами. Это изменит существующую легенду вместо создания новой. Ниже вы найдете свой пример, слегка измененный.

import pylab
pylab.plot(0,0,'ro', label = 'one point')
pylab.legend(loc = "lower left")
# Change the number of markers shown in the legend
pylab.legend(numpoints = 1, loc = "lower left")

pylab.show()

надеюсь, что это помогает.


то, что вы видите в легенде, на самом деле это Line2D. Изменение numpoints после того, как эта строка была создана, не будет обновлять указанную строку, поэтому вам придется получить дескриптор на Line2D "объект" и удалить одну из точек вручную:

import pylab
pylab.plot(0,0,'ro', label = 'one point')
legend = pylab.legend(loc = "lower left")
markers = legend.get_children()[0].get_children()[1].get_children()[0].get_children()[0].get_children()[0].get_children()[1]
markers.set_data(map(pylab.mean, markers.get_data()))
pylab.show()

на get_children() цепь требуется, потому что matplotlib обертывает линию в несколько слоев горизонтальных и вертикальных пакетов. Приведенного выше фрагмента должно быть достаточно, чтобы дать вам общее представление, но в реальном приложении предпочтительный способ получить ручка будет следовать подсказка легенды руководства по legend handlers и использовать индивидуальные HandlerLine2D это хранит линию в некотором роде.


если бы это был я, я бы поместил его в другой текстовый файл, чтобы сделать это, так как это будет легче изменить и отслеживать, особенно если у вас есть много кода до и после этого.

чтобы открыть файл для записи, мы устанавливаем второй параметр на " w "вместо"r".(of fobj = open("ad_lesbiam.txt", "r")) чтобы фактически записать данные в этот файл, мы используем метод write() объекта дескриптора файла.

давайте начнем с очень простого и понятного примера:

fh = open("example.txt", "w")
fh.write("To write or not to write\nthat is the question!\n")
fh.close()

особенно если вы пишете в файл, вы никогда не должны забывать закрыть дескриптор файла снова. В противном случае вы рискуете оказаться в несогласованном состоянии ваших данных.

вы часто найдете оператор with для чтения и записи файлов. Преимущество заключается в том, что файл будет автоматически закрыт после отступа блока после завершения выполнения with:

with open("example.txt", "w") as fh:
    fh.write("To write or not to write\nthat is the question!\n")

наш первый пример также может быть переписан следующим образом: с заявлением:

with open("ad_lesbiam.txt") as fobj:
    for line in fobj:
        print(line.rstrip())

пример для одновременного чтения и записи:

fobj_in = open("ad_lesbiam.txt")
fobj_out = open("ad_lesbiam2.txt","w")
i = 1
for line in fobj_in:
    print(line.rstrip())
    fobj_out.write(str(i) + ": " + line)
    i = i + 1
fobj_in.close()
fobj_out.close()

к твоему сведению. Каждая строка входного текстового файла имеет префикс по номеру строки