2016-07-13 3 views
2

This site показывает многие (все?) Параметры rc, которые могут быть скорректированы на графиках Matplotlib либо через файл matplotlibrc, либо с использованием matplotlib.rcParams[] в сценарии Python. Я не вижу способа настроить ширину рамки поля легенды, используя параметры, перечисленные на этом сайте. Я знаю, что можно изменить ширину строки в поле «вручную», то есть в скрипте (for example), но я надеюсь на способ установить его с помощью matplotlib.rcParams[] или в файле matplotlibrc. Как я могу это сделать?Matplotlib: есть ли способ rcParams отрегулировать ширину границы легенды?

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

В некоторых сценариях я вызываю легенду как pyplot.legend(), а в других я вызываю ее как ax.legend().

+0

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

+0

@MadPhysicist, автоматический способ его установить? – Joshua

+0

Я предполагаю, что вы можете автоматизировать что-то вроде 'matplotlib.legend.Legend.myMagicProperty = 25', а также вы можете' matplotlib.rcParams ['my.magic.param'] = 25'. –

ответ

3

В зависимости от того, что вы пытаетесь сделать, на самом деле можно установить ширину границы легенды через rcParams.

TL; DR

Набор patch.linewidth в matplotlibrc или еще лучше написать функцию обертку две строки для legend и использовать вместо в ваших сценариях.

Long Version

Глядя на код legend, вы можете увидеть, что кадр сохраняется как matplotlib.patched.FancyBBoxPatch объект, который представляет собой тип matplotlib.patches.Patch. Patch объекты получают ширину линии по умолчанию от matplotlib.rcParams['patch.linewidth']. Это означает, что если вы установили patch.linewidth в matplotlibrc, размер границы легенды изменится.

Аналогичная модификация patch.edgecolor изменит цвет границы, но patch.facecolor будет игнорироваться для легенд.

Вот пример кода для иллюстрации изменений, с некоторыми выходами:

>>> import matplotlib as mpl 
>>> from matplotlib import pyplot as plt 
>>> mpl.rcParams['patch.linewidth'] 
1.0 
>>> plt.plot((0, 1), label='a')[0].axes.legend() 
<matplotlib.legend.Legend object at 0x7f6d7b0a0e48> 
>>> mpl.rcParams['patch.linewidth'] = 15 
>>> plt.plot((0, 1), label='a')[0].axes.legend() 
<matplotlib.legend.Legend object at 0x7f6d7ae20908> 

normal line legend

15px line legend

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

Лучший путь

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

from matplotlib.axes import Axes 

def add_legend(ax, *args, **kwargs): 
    """ 
    Adds a legend to the specified axes, along with some common formatting. All additional arguments are the same as for `ax.legend`. 
    """ 
    legend = _originalFn(ax, *args, **kwargs) 
    legend.set_linewidth(15) 
    return legend 

if Axes.legend is not add_legend: 
    _originalFn = Axes.legend 
    Axes.legend = add_legend 

Этот сценарий структурирован таким образом, что вы никогда не нужно вызвать add_legend вручную.Просто импортируйте подклассы сценариев matplotlib.axes.Axes, чтобы вызов ax.legend(...), как и раньше, установил ширину полосы легенд по умолчанию до 15 пунктов.

Сценарий выше будет работать для звонков в ax.legend где ax является Axes экземпляр и plt.legend, поскольку plt.legend действительно только делегатов gca().legend с некоторой дополнительной обработки.

Этот механизм подкласса будет работать, даже если ваша программа состоит из нескольких сценариев/модулей, которые импортируют общий скрипт. Это связано с тем, что Python на самом деле не перезагружает модуль после первого раза и вместо этого просто вернет ссылку на него со всеми атрибутами без изменений. Вещи разрываются, если вы начнете использовать importlib.reload, но это только очень отдаленная возможность.

Смежные вопросы