Matplotlib axes.legend меняет размер изображения (аспект изображения?) - PullRequest
0 голосов
/ 31 октября 2018

Этот вопрос, скорее всего, связан с предыдущим вопросом, который у меня возник, возникший при рефакторинге некоторого кода (для повторного использования объекта осей matplotlib), который связан здесь . В этом вопросе описана проблема, при которой imshow изменил бы параметр image.aspect.

Сейчас я пытаюсь решить проблему, которая дает похожий эффект, но я не смог ее исправить, принудительно установив параметр image.aspect в auto, что было моей первой мыслью, поскольку, похоже, что она как-то настраивается. Мне также не удалось найти что-либо, копающееся в основной документации, найденной здесь .

Вот картинки , иллюстрирующие проблему (скрытые записи легенды):

Ожидаемое поведение (ограниченное количество записей легенды) enter image description here

Неожиданное поведение (большое количество записей легенды) enter image description here

A MVCE для вышеуказанного поведения (с полными бессмысленными данными) приведено ниже, где поведение можно переключать между ожидаемым и неожиданным (для меня) переключением верхнего предела в строке for i in range(1,10): до 50.

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg
)
import tkinter as tk
import numpy
from matplotlib import image, figure

class Foo(object):
    @classmethod
    def run(cls):
        root = tk.Tk()
        Foo(root)
        root.mainloop()

    def __init__(self, master):
        self.fig = figure.Figure(figsize=(12,6))
        self.fig.set_tight_layout(True)
        self.axes = self.fig.add_subplot(111)
        self.axes.axis('off')
        self.canvas = FigureCanvasTkAgg(self.fig, master=master)
        self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=tk.YES)
        self.canvas.draw()
        self.data = []
        # Adjust the upper value to 10 or 50
        for i in range(1,10):
            self.axes.plot(range(0,100),numpy.random.randint(1,100,100), label=str(i))
        self.axes.legend()


if __name__ == '__main__':
    Foo.run()

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

1 Ответ

0 голосов
/ 31 октября 2018

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

В версиях matplotlib> 3 у художника есть свойство set_in_layout ( docs для loo_layout ), для которого вы можете установить значение True или False, чтобы включить или исключить его из вычислений, выполненных, когда tight_layout называется. Поэтому вы можете изменить ваш __init__, чтобы он выглядел примерно так:

def __init__(self, master):
    self.fig = figure.Figure(figsize=(12,6))
    self.fig.set_tight_layout(True)
    self.axes = self.fig.add_subplot(111)
    self.axes.axis('off')
    self.canvas = FigureCanvasTkAgg(self.fig, master=master)
    self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=tk.YES)
    self.canvas.draw()
    self.data = []
    # Adjust the upper value to 10 or 50
    for i in range(1,50):
        self.axes.plot(range(0,100),numpy.random.randint(1,100,100), label=str(i))
    self.leg = self.axes.legend()
    self.leg.set_in_layout(False)  # set to False so it's not used in tight_layout calculation!

Альтернативный (но не идеальный) вариант - удалить self.fig.set_tight_layout(True) и самостоятельно настроить пробелы, используя self.fig.subplots_adjust(), однако для получения желаемого результата может потребоваться ручная настройка параметров. .

...