2013-06-17 8 views
6

Die Legende der Darstellung einer sekundären Achse ist irgendwie transparent für die Darstellung der anderen Achse. Ein minimales Beispiel, das Problem zu reproduzieren:Legende Transparenz, bei Verwendung der sekundären Achse

import matplotlib.pyplot as plt 

ax1 = plt.subplot(111) 
ax2 = ax1.twinx() 
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r') 
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1') 
ax1.legend(loc=2) 
plt.show() 

Der Ausgang ich erhalte, ist: Faulty plot

Wie Sie die Legende für die blaue Handlung ist overdrawn durch das rote Grundstück sehen. Das Umordnen der Zeichnungsbefehle, das Ändern des Alpha-Werts oder das Ändern der Z-Ordnungen der Objekte hilft nicht.

Gibt es eine Möglichkeit, die Legende für alle Plots undurchsichtig zu machen?

EDIT: @tcaswell: Während Ihre Antwort für eine einzelne Legende funktioniert, funktioniert es nicht, wenn beide Achsen eine separate Legende haben. Im folgenden Code habe ich ein Label für ax2:

import matplotlib.pyplot as plt 
plt.figure() 
ax1 = plt.subplot(111) 
ax2 = ax1.twinx() 
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r', label='ax2') 
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1') 
ax1.legend(loc=2) 
ax2.legend(loc=1) 

ax1.set_zorder(1) # make it on top 
ax1.set_frame_on(False) # make it transparent 
ax2.set_frame_on(True) # make sure there is any background 

plt.show() 

mit folgendem Ergebnis:

Faulty plot with two legends

Während Ihr allgemeineren Ansatz löst dieses Problem, indem Figure.legend leider die Legende außerhalb der Orte Handlung. Sie explizit mit loc zu plazieren ist etwas mühsam und funktioniert nicht gut beim Skalieren des Plots. Gibt es eine bessere Lösung?

Antwort

8

Probleme treten auf, weil matplotlib die Plots rendert. Standardmäßig wird die zweite Achse nach die erste gerendert (sie haben die gleiche zorder, so dass sie in der Reihenfolge rendern, in der sie hinzugefügt wurden).

bekommen, was Sie wollen, müssen Sie nur ein paar Dinge über Ihre Achsen zwicken:

figure() 
ax1 = plt.subplot(111) 
ax2 = ax1.twinx() 
ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r') 
ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1') 
ax1.legend(loc=2) 

ax1.set_zorder(1) # make it on top 
ax1.set_frame_on(False) # make it transparent 
ax2.set_frame_on(True) # make sure there is any background 

plt.show() 

Wir die zorder von ax1 höher eingestellt sein, damit es später gemacht wird, aber wenn wir genau das tun, die zweite Achse ist überhaupt nicht sichtbar, da sie alle unter dem Rahmen (weißer Hintergrund und Kasten) von ax1 gezeichnet ist. Um das zu beheben, drehen wir den Rahmen auf ax1 (so können wir ax2 sehen). Aber jetzt haben wir keine Hintergrund oder Bounding Box überhaupt. Wir können dann den Rahmen für ax2 wieder einschalten, was uns den gewünschten Effekt gibt.

Das oben beschriebene Verfahren ist ad-hoc und nicht die Regel, wenn Sie sicherstellen möchten, dass Sie Achsen ist über alle Achsen, müssen Sie Figure.ledgend(), verwenden, die eine figure ist, nicht axes Funktion. Derzeit wird es nicht auto-magisch Ihre Etiketten finden, so dass Sie in den Handgriffen und Etiketten explizit passieren müssen:

fig = figure() 

ax1 = plt.subplot(111) 
ax2 = ax1.twinx() 

ln2, = ax2.plot([1, 2, 3], [0.3, 0.2, 0.1], 'r', label='ax2') 
ln1, = ax1.plot([1, 2, 3], [1, 2, 3], 'b', label='ax1') 

interesting_lines = [ln1, ln2] 

fig.legend(*zip(*[(il, il.get_label()) for il in interesting_lines]), loc=2) 

plt.show() 

Beachten Sie, dass diese Legende jetzt Figur Koordinaten platziert werden.

+0

Danke! Das hat schon sehr geholfen.Leider löst es mein Problem nicht vollständig, siehe meine Bearbeitung. – bzn

+0

@bzn Ich glaube nicht, dass es eine bessere Lösung gibt, weil mpl die Bilder (Schicht für Schicht) rendert, nichts in den unteren Achsen kann von den oberen Achsen "über" sein. Sie sollten eine neue Frage zu besseren Möglichkeiten zum Platzieren der Figurenlegende öffnen. – tacaswell

0

Ich habe bbox_to_anchor verwendet, um die Position beider Legenden festzulegen, und sie wurden oben angezeigt. Ich wusste nicht warum, aber es hat funktioniert. zB

ax1.legend(bbox_to_anchor=(0.16,0.2)) 
ax2.legend(bbox_to_anchor=(1,0.2)) 
Verwandte Themen