2016-06-03 1 views
5

Я уже задал вопрос о том, как построить различные столбцы из блока данных pandas на отдельных подзаговорах здесь: Plot multiple lines on subplots with pandas df.plot и получил отличный ответ. Теперь я пытаюсь максимально использовать пространство на сюжете, и легенда оказывается проблемой. То, что я хотел бы сделать, это поставить 3 или 4 серии по одной легенде, а остальные - на другую, чтобы я мог поместить каждого в угол, где они будут хорошо вписываться.Несколько легенд на подзаголовках pandas df.plot?

Я пытался использовать методы, описанные в Matplotlib, как показано здесь:

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

, но я получаю вопросы, которые либо с помощью панд df.plot, или от попыток реализовать на сюжетном , Вот то, что я пробовал:

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 

и вот что я получаю:

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

Кто-нибудь есть работа вокруг?

ответ

4

Вы попали в заблуждение ложным предположением о природе gca(). Я тоже был удивлен, поэтому я решил добавить ответ (в противном случае мы в основном говорим о проблеме с типографским типом). Кроме того, я отмечаю, что проблема не имеет ничего общего с пандами.

Вот минимальный пример воспроизведения вашей проблемы без панд:

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) 

Так в чем проблема? Внимательно посмотрите на сообщение об ошибке:

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

(выделено мной). Смотри:

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

Проблема заключается в том, что даже если вы работаете на ax1, что «график текущих осей» gca() также известный указует на ax2, то Axes созданы позднее.

Решение теперь просто: будет явно перерисовки вызова (помните, явно лучше, чем неявное):

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 

И он жив!

result

+1

Это делает много смысла, и я склонен согласиться с вашим мнением о будучи явным. Было бы неплохо, если бы пример matplotlib был явным. Re: использование matplotlib напрямую - я нашел, что панды замышляют быть хорошими с точки зрения рабочего процесса для построения большого количества серий, подобных вещей. Благодаря! – spizwhiz

+0

@spizwhiz спасибо за отзыв, я не знаком с пандами, но я видел некоторые проблемы ранее, которые были решены с помощью 'plt.plot'. Очевидно, вы должны использовать все, что работает для вас больше всего. И вещь о том, чтобы быть явным, включена в [Zen of Python] (https://www.python.org/dev/peps/pep-0020/) :) –

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

  • Нет связанных вопросов^_^