2011-03-30 16 views
155

twinx() kullanarak iki y eksenli bir çizimim var. Ayrıca hatlarına etiketleri vermek ve legend() bunları göstermek istiyorum, ama sadece efsane bir eksenin etiketleri almak için başarılı:Twinx ile ikinci eksen(): nasıl efsane eklenir?

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib import rc 
rc('mathtext', default='regular') 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.plot(time, Swdown, '-', label = 'Swdown') 
ax.plot(time, Rn, '-', label = 'Rn') 
ax2 = ax.twinx() 
ax2.plot(time, temp, '-r', label = 'temp') 
ax.legend(loc=0) 
ax.grid() 
ax.set_xlabel("Time (h)") 
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)") 
ax2.set_ylabel(r"Temperature ($^\circ$C)") 
ax2.set_ylim(0, 35) 
ax.set_ylim(-20,100) 
plt.show() 

Yani sadece ilk eksenin etiketleri almak efsane, ikinci eksenin etiketi 'temp' değil. Bu üçüncü etiketi efsaneye nasıl ekleyebilirim? Eğer tüm etiketleri istiyorsanız

enter image description here

Ama:

ax2.legend(loc=0) 

Bu alırsınız:

enter image description here

cevap

204

Kolayca satır ekleyerek ikinci bir efsane ekleyebilir bir efsane sonra böyle bir şey yapmalısınız:

.210
import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib import rc 
rc('mathtext', default='regular') 

time = np.arange(10) 
temp = np.random.random(10)*30 
Swdown = np.random.random(10)*100-10 
Rn = np.random.random(10)*100-10 

fig = plt.figure() 
ax = fig.add_subplot(111) 

lns1 = ax.plot(time, Swdown, '-', label = 'Swdown') 
lns2 = ax.plot(time, Rn, '-', label = 'Rn') 
ax2 = ax.twinx() 
lns3 = ax2.plot(time, temp, '-r', label = 'temp') 

# added these three lines 
lns = lns1+lns2+lns3 
labs = [l.get_label() for l in lns] 
ax.legend(lns, labs, loc=0) 

ax.grid() 
ax.set_xlabel("Time (h)") 
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)") 
ax2.set_ylabel(r"Temperature ($^\circ$C)") 
ax2.set_ylim(0, 35) 
ax.set_ylim(-20,100) 
plt.show() 

size verecektir hangisi bu:

enter image description here

+15

teşekkür ederiz! Bu kesinlikle yapacak. Ben sadece matplotlib'in daha fazla otomatik çözümü olmadığını biraz talihsiz buluyorum. – joris

+0

Bu, 'errorbar' grafikleriyle başarısız oluyor. Doğru şekilde işleyen bir çözüm için aşağıya bakın: http://stackoverflow.com/a/10129461/1319447 – Davide

+0

İki örtüşen efsaneyi önlemek için iki .legend (loc = 0) belirtdiğim gibi iki tane belirtmelisiniz. Lejant konum değeri için farklı değerler (her ikisi de 0'dan farklı). Bakınız: http://matplotlib.org/api/legend_api.html – Roalt

99

Bu işlevselliği yeni olup olmadığından emin değilim, ama aynı zamanda oldukça çizgilerin takip yerine) (yöntemini get_legend_handles_labels kullanabilir ve Etiketleri siz yapabilirsiniz :

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib import rc 
rc('mathtext', default='regular') 

pi = np.pi 

# fake data 
time = np.linspace (0, 25, 50) 
temp = 50/np.sqrt (2 * pi * 3**2) \ 
     * np.exp (-((time - 13)**2/(3**2))**2) + 15 
Swdown = 400/np.sqrt (2 * pi * 3**2) * np.exp (-((time - 13)**2/(3**2))**2) 
Rn = Swdown - 10 

fig = plt.figure() 
ax = fig.add_subplot(111) 

ax.plot(time, Swdown, '-', label = 'Swdown') 
ax.plot(time, Rn, '-', label = 'Rn') 
ax2 = ax.twinx() 
ax2.plot(time, temp, '-r', label = 'temp') 

# ask matplotlib for the plotted objects and their labels 
lines, labels = ax.get_legend_handles_labels() 
lines2, labels2 = ax2.get_legend_handles_labels() 
ax2.legend(lines + lines2, labels + labels2, loc=0) 

ax.grid() 
ax.set_xlabel("Time (h)") 
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)") 
ax2.set_ylabel(r"Temperature ($^\circ$C)") 
ax2.set_ylim(0, 35) 
ax.set_ylim(-20,100) 
plt.show() 
kolaylıkla balta içinde satır ekleyerek istediğini elde edebilirsiniz
+1

arsaların lejantlarla örtüştüğü eksenlerin üstesinden gelebilecek çözüm (son eksenler efsaneleri çizen son eksendir) –

+2

Bu çözüm ayrıca 'errorbar' grafikleriyle de çalışır, kabul edileni başarısız olurken (bir satırı ve hata çubuklarını ayrı olarak gösterir) ve bunların hiçbiri doğru etiketle olmaz. Ayrıca, daha basittir: – Davide

+0

hafif yakalama: 'ax2' için etiketin üzerine yazmak isterseniz işe yaramıyor ve –

23

:

ax.plot(0, 0, '-r', label = 'temp') 

veya

ax.plot(np.nan, '-r', label = 'temp') 

Bu bir şeyi çizmek ancak balta efsanesine bir etiket eklersiniz.

Bence bu daha kolay bir yol. İkinci eksende sadece birkaç satıra sahip olduğunuzda hatları otomatik olarak izlemek gerekli değildir, çünkü yukarıdaki gibi sabitleme yapmak oldukça kolay olacaktır. Her neyse, neye ihtiyacın olduğuna bağlı.

bütün kod aşağıdaki gibidir:

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib import rc 
rc('mathtext', default='regular') 

time = np.arange(22.) 
temp = 20*np.random.rand(22) 
Swdown = 10*np.random.randn(22)+40 
Rn = 40*np.random.rand(22) 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax2 = ax.twinx() 

#---------- look at below ----------- 

ax.plot(time, Swdown, '-', label = 'Swdown') 
ax.plot(time, Rn, '-', label = 'Rn') 

ax2.plot(time, temp, '-r') # The true line in ax2 
ax.plot(np.nan, '-r', label = 'temp') # Make an agent in ax 

ax.legend(loc=0) 

#---------------done----------------- 

ax.grid() 
ax.set_xlabel("Time (h)") 
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)") 
ax2.set_ylabel(r"Temperature ($^\circ$C)") 
ax2.set_ylim(0, 35) 
ax.set_ylim(-20,100) 
plt.show() 

arsa aşağıdaki gibidir:

enter image description here


Güncelleme:

ax.plot(np.nan, '-r', label = 'temp') 

: Daha iyi bir versiyonunu eklemek Bu wil plot(0, 0) eksen aralığını değiştirebilirken hiçbir şey yapmam.

+2

Bunu beğendim. Sistemin "hileli" olduğu gibi çirkin bir şekilde, ancak uygulanması çok kolay –

4

Birden çok y eksenini ve tüm etiketleri tek bir göstergede görüntülemek için host_subplot kullanan bir resmi matplotlib örneğini buldum. Hiçbir geçici çözüm gerekli değildir. Şimdiye kadar bulduğum en iyi çözüm.cevap verecek duruma http://matplotlib.org/examples/axes_grid/demo_parasite_axes2.html

from mpl_toolkits.axes_grid1 import host_subplot 
import mpl_toolkits.axisartist as AA 
import matplotlib.pyplot as plt 

host = host_subplot(111, axes_class=AA.Axes) 
plt.subplots_adjust(right=0.75) 

par1 = host.twinx() 
par2 = host.twinx() 

offset = 60 
new_fixed_axis = par2.get_grid_helper().new_fixed_axis 
par2.axis["right"] = new_fixed_axis(loc="right", 
            axes=par2, 
            offset=(offset, 0)) 

par2.axis["right"].toggle(all=True) 

host.set_xlim(0, 2) 
host.set_ylim(0, 2) 

host.set_xlabel("Distance") 
host.set_ylabel("Density") 
par1.set_ylabel("Temperature") 
par2.set_ylabel("Velocity") 

p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density") 
p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature") 
p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity") 

par1.set_ylim(0, 4) 
par2.set_ylim(1, 65) 

host.legend() 

plt.draw() 
plt.show() 
+0

Yığın Taşımıma Hoş Geldiniz!Hedef siteye ulaşılamaması veya sürekli olarak çevrimdışı kalması durumunda lütfen bağlantının en alakalı bölümünü belirtin. [Nasıl iyi bir cevap yazabilirim?] (Http://stackoverflow.com/help/how-to-answer). Gelecekte daha güncel sorulara odaklanın, bu yaklaşık 4 yaşında. – ByteHamster

+0

Gerçekten iyi bir keşif ama keşke örnekte öğrendiklerinizi almayı, OP'nin MWE'sine uygulamanızı ve bir resim eklemenizi isterdim. – aeroNotAuto

3

hızlı kesmek ..

kutusunun çerçeveyi çıkarın ve elle yanyana iki efsaneleri yerleştirin. Böyle bir şey .. loc tanımlama grubu soldan sağa ve grafikte yerini temsil alt-üst yüzdeleri

ax1.legend(loc = (.75,.1), frameon = False) 
ax2.legend(loc = (.75, .05), frameon = False) 

.

4

matplotlib sürüm 2.1'den itibaren şekil efsanesini kullanabilirsiniz. Bunun yerine eksenler ax gelen kulplu bir efsaneyi üretir ax.legend() ait bir şekildeki tüm subplots tüm kolları toplayacak bir şekil açıklaması

fig.legend(loc=1)

oluşturabilir. Şekil efsanesi olduğu için, figürün köşesine yerleştirilir ve loc argümanı, şekle göredir. eksenleri geri efsane yerleştirmek amacıyla

enter image description here

import numpy as np 
import matplotlib.pyplot as plt 

x = np.linspace(0,10) 
y = np.linspace(0,10) 
z = np.sin(x/3)**2*98 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.plot(x,y, '-', label = 'Quantity 1') 

ax2 = ax.twinx() 
ax2.plot(x,z, '-r', label = 'Quantity 2') 
fig.legend(loc=1) 

ax.set_xlabel("x [units]") 
ax.set_ylabel(r"Quantity 1") 
ax2.set_ylabel(r"Quantity 2") 

plt.show() 

, tek bir bbox_to_anchor ve bbox_transform kaynağı olacaktır. İkincisi, efsanenin içinde bulunması gereken eksenlerin eksen dönüşümü olacaktır. İlk, eksen koordinatlarında verilen loc tarafından tanımlanan kenarın koordinatları olabilir.

fig.legend(loc=1, bbox_to_anchor=(1,1), bbox_transform=ax.transAxes) 

enter image description here

+0

Yani, 2.1 sürümü zaten çıktı mı? Ama Anaconda 3'te, matplotlib 'conda'nın yeni sürümleri bulunamadığını denedim, hala v.2.0.2 kullanıyorum – StayFoolish

İlgili konular