2016-06-03 10 views
5

Ich hatte zuvor eine Frage darüber gestellt, wie man verschiedene Spalten von einem Pandas-Dataframe auf separaten Teilplots hier plotten kann: Plot multiple lines on subplots with pandas df.plot, und bekam eine gute Antwort. Jetzt versuche ich, den Platz auf der Handlung zu maximieren, und die Legende erweist sich als ein Problem. Ich würde gerne 3 oder 4 Serien auf eine Legende und die restlichen auf die andere legen, damit ich sie in eine Ecke legen kann, wo sie gut passen.Mehrere Legenden auf Pandas df.plot Subplots?

Ich habe versucht, die Methoden für matplotlib beschrieben zu verwenden, hier gezeigt:

from matplotlib.pyplot import * 

p1, = plot([1,2,3], label="test1") 
p2, = plot([3,2,1], label="test2") 

l1 = legend([p1], ["Label 1"], loc=1) 
l2 = legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
gca().add_artist(l1) # add l1 as a separate artist to the axes 

show() 

, aber ich bin immer Fragen, die entweder von der Nutzung des Pandas df.plot sind, oder von dem Versuch, auf einer Nebenhandlung zu implementieren . Hier ist, was ich versucht habe:

f, (ax1, ax2) = plt.subplots(ncols = 2) 

p1 = dfcomb.iloc[:,:3].plot(ax=ax1, figsize=(14,5)) 
p2 = dfcomb.iloc[:,3:6].plot(ax=ax1, figsize=(14,5)) 
l1 = ax1.legend([p1], ["Label 1"], loc=1) 
l2 = ax1.legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
gca().add_artist(l1) # add l1 as a separate artist to the axes 

und hier ist, was ich bekommen:

--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-108-d3206d8ce17d> in <module>() 
    15 l1 = ax1.legend([p1], ["Label 1"], loc=1) 
    16 l2 = ax1.legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
---> 17 gca().add_artist(l1) 
    18 
    19 ax1.set_xlabel('Suction (cm)') 

C:\Anaconda\lib\site-packages\matplotlib\axes\_base.pyc in add_artist(self, a) 
    1646   Returns the artist. 
    1647   """ 
-> 1648   a.axes = self 
    1649   self.artists.append(a) 
    1650   self._set_artist_props(a) 

C:\Anaconda\lib\site-packages\matplotlib\artist.pyc in axes(self, new_axes) 
    235   if (new_axes is not None and 
    236     (self._axes is not None and new_axes != self._axes)): 
--> 237    raise ValueError("Can not reset the axes. You are " 
    238        "probably trying to re-use an artist " 
    239        "in more than one Axes which is not " 

ValueError: Can not reset the axes. You are probably trying to re-use an artist in more than one Axes which is not supported 

Wer noch ein work-around?

Antwort

4

Sie wurden von einer falschen Annahme über die Natur gca() überfallen. Ich war auch überrascht, weshalb ich beschloss, eine Antwort hinzuzufügen (ansonsten sprechen wir meistens von einem Tippfehler-Problem). Ich stelle auch fest, dass das Problem nichts mit Pandas zu tun hat.

Hier ist ein minimales Beispiel reproduzieren Ihr Problem ohne Pandas:

import matplotlib.pyplot as plt 

f, (ax1, ax2) = plt.subplots(ncols = 2) 
p1, = ax1.plot([1,2,3], label="test1") 
p2, = ax1.plot([3,2,1], label="test2") 

l1 = ax1.legend([p1], ["Label 1"], loc=1) 
l2 = ax1.legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
plt.gca().add_artist(l1) 

Also, was ist das Problem? Schauen Sie sich die Fehlermeldung genauer an:

(Hervorhebung von mir). Schauen Sie:

>>> ax1 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd83abf7e10> 
>>> ax2 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd83a992850> 
>>> plt.gca() 
<matplotlib.axes._subplots.AxesSubplot at 0x7fd83a992850> 

Das Problem ist, dass, obwohl Sie auf ax1 arbeiten, die „Grafik aktuelle Achsen“ auch bekannt als gca() Punkte auf ax2, die Axes neueste erstellt.

Die Lösung jetzt einfach: mit dem Nachzug-Aufruf explizit sein (denken Sie daran, explizite ist besser als implizite):

import matplotlib.pyplot as plt 

f, (ax1, ax2) = plt.subplots(ncols = 2) 
p1, = ax1.plot([1,2,3], label="test1") 
p2, = ax1.plot([3,2,1], label="test2") 
# or whatever plots you prefer using pandas 
# (I'd use matplotlib directly anyway) 

l1 = ax1.legend([p1], ["Label 1"], loc=1) 
l2 = ax1.legend([p2], ["Label 2"], loc=4) # this removes l1 from the axes. 
ax1.add_artist(l1) # <-- just change here, refer to ax1 explicitly 

Und es ist lebendig!

result

+1

Das viel Sinn macht, und ich neige dazu, mit Blick auf sein persönliches Vertrauen zu vereinbaren. Wäre schön, wenn das Beispiel von matplotlib auch explizit wäre. Re: mit Matplotlib direkt - ich habe Pandas Plotten gefunden, um in Bezug auf den Workflow für die Plotting eine große Anzahl von Serien, solche Dinge. Vielen Dank! – spizwhiz

+0

@spizwhiz danke für das Feedback, ich bin nicht vertraut mit Pandas, aber ich habe einige Probleme früher gesehen, die mit "plt.plot" stattdessen gelöst wurden. Natürlich solltest du das verwenden, was am besten für dich funktioniert. Und die Sache, explizit zu sein, ist im [Zen of Python] (https://www.python.org/dev/peps/pep-0020/) enthalten :) –

Verwandte Themen