2016-07-13 9 views
2

This site zeigt viele (alle?) Rc-Parameter, die in Matplotlib-Plots angepasst werden können, entweder über die Datei matplotlibrc oder matplotlib.rcParams[] in einem Python-Skript. Ich kann keine Möglichkeit sehen, die Breite der Rahmenbox einer Legende mithilfe der auf dieser Site aufgelisteten Parameter anzupassen. Ich weiß, dass es möglich ist, die Linienbreite der Box "manuell" zu ändern, d. H. Im Skript (for example), aber ich hoffe auf eine Möglichkeit, es unter Verwendung matplotlib.rcParams[] oder in einer matplotlibrc Datei zu setzen. Wie könnte ich das tun?Matplotlib: Gibt es eine rcParams-Methode zum Anpassen der Legendenrandbreite?

Der Grund, warum ich ein automatisiertes, externes (oder zumindest leicht kopieren und -verlegbar) haben möchte, ist, weil ich mehrere Zahlen habe, mit mehreren verschiedenen Python-Skripten, die diese verschiedenen Zahlen produzieren, und ich möchte so einfach einen Weg Es ist möglich, ein einheitliches Aussehen zwischen den einzelnen Figuren über die verschiedenen Python-Skripte hinweg aufrechtzuerhalten.

In einigen Skripts rufe ich für eine Legende als pyplot.legend() und in anderen ich es als ax.legend() nennen.

+0

Sie können dies möglicherweise nicht über rcParams tun, aber ich wette, es gibt eine Eigenschaft, die Sie irgendwo in der Legendenklasse festlegen können, um dies zu tun. –

+0

@MadPhysicist, eine automatisierte Möglichkeit, es zu setzen? – Joshua

+0

Ich gehe davon aus, dass Sie so etwas wie 'matplotlib.legend.Legend.myMagicProperty = 25' sowie' matplotlib.rcParams ['my.magic.param'] = 25' automatisieren können. –

Antwort

3

Je nachdem, was Sie zu tun versuchen, können Sie die Breite des Legendenrahmens möglicherweise über rcParams festlegen.

TL; DR

Set patch.linewidth in matplotlibrc oder noch besser, schreiben Sie eine zweizeilige Wrapper-Funktion für legend und verwendet, die stattdessen in Ihrer Skripts.

Long Version

auf den Code der Suche nach legend, können Sie sehen, dass der Rahmen als Objekt matplotlib.patched.FancyBBoxPatch gespeichert, die eine Art von matplotlib.patches.Patch ist. Patch Objekte erhalten ihre Standardlinienbreite von matplotlib.rcParams['patch.linewidth']. Das heißt, wenn Sie patch.linewidth in matplotlibrc setzen, ändert sich die Größe des Legendenrahmens. Eine ähnliche Änderung an patch.edgecolor wird die Rahmenfarbe ändern, aber patch.facecolor wird für Legenden ignoriert.

Hier ist ein Codebeispiel die Änderung zu veranschaulichen, mit einigen Ausgaben:

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

Die offensichtliche Frage ist hier, dass, wenn Sie andere Flecken auf Ihre Diagramme zeichnen , wird die Standardlinienbreite abgeworfen. Sie können dies natürlich abschwächen, indem Sie die Linienbreite für alle von Ihnen erstellten Patches manuell auf 1 zurücksetzen. Dies ist eindeutig keine optimale Lösung.

A Better Way

Eine viel bessere Lösung wäre, ein kleines Skript zu erstellen, die Sie zwischen all Ihrem Chart-Generation Skripte teilen. Hier ist ein Beispiel für ein solches Skript:

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 

Dieses Skript ist so strukturiert, so dass Sie nicht immer brauchen add_legend manuell aufrufen.Importieren Sie einfach die Unterklassen des Skripts matplotlib.axes.Axes, so dass der Aufruf der ax.legend(...) wie zuvor die Standardbreite der Legendenbegrenzung auf 15 Punkte setzt.

Das Skript oben wird für Anrufe in ax.legend arbeiten, wo ax eine Axes Instanz ist und auf plt.legend, da plt.legend wirklich nur Delegierten gca().legend mit einigen zusätzlichen Verarbeitung.

Dieser Unterklassenmechanismus funktioniert auch dann, wenn Ihr Programm aus mehreren Skripts/Modulen besteht, die das gemeinsame Skript importieren. Dies liegt daran, dass Python das Modul nach dem ersten Mal nicht wirklich neu lädt und stattdessen nur einen Verweis darauf zurückgibt, wobei alle Attribute intakt sind. Die Dinge werden brechen, wenn Sie anfangen, importlib.reload zu verwenden, aber das ist nur eine sehr entfernte Möglichkeit.