2012-08-09 14 views
11

Kare eksenleri korurken bir alt grafikte bir dendrogram ve başka bir ısı haritası ile basit bir alt çizim yapmaya çalışıyorum.Matplotlib'de ısı haritalarıyla kare alt pikseller nasıl oluşturulur?

from scipy.cluster.hierarchy import linkage 
from scipy.cluster.hierarchy import dendrogram 
from scipy.spatial.distance import pdist 

fig = plt.figure(figsize=(7,7)) 
plt.subplot(2, 1, 1) 
cm = matplotlib.cm.Blues 
X = np.random.random([5,5]) 
pmat = pdist(X, "euclidean") 
linkmat = linkage(pmat) 
dendrogram(linkmat) 
plt.subplot(2, 1, 2) 
labels = ["a", "b", "c", "d", "e", "f"] 
Y = np.random.random([6,6]) 
plt.xticks(arange(0.5, 7.5, 1)) 
plt.gca().set_xticklabels(labels) 
plt.pcolor(Y) 
plt.colorbar() 

bu şu sonuçları verir:

enter image description here

ama sorunlar eksenleri kare olmadığını, ve Colorbar ikinci subplot parçası olarak kabul edilir Ben aşağıdakileri deneyin. Bunun yerine, arsa dışında asmak ve dendrogram kutusu ve ısı haritası kutusunun hem kare hem de birbiriyle hizalanmış olmasını istiyorum (yani aynı boyutta.)

Kare eksenler elde etmek için aspect='equal' kullanmayı denedim ...

enter image description here

yerine aspect='equal' her subplot sonra plt.axis('equal') kullanmaya çalışırsanız, bu garip kareler ısı haritası ancak sınırlayıcı kutusunu belgelerine anlaşılacağı gibi subplot arayarak, ancak bu bu vererek arsa harap (aşağıya bakınız), dendrogramı tamamen yok ederken ve aynı zamanda xtick etiketlerinin hizalanmasını bozarken .... - Bu karmaşıklığa sebebiyet veren:

enter image description here

nasıl

bu düzeltilebilir? özetlemek gerekirse, çok basit bir şeyi çizmeye çalışıyorum: üstteki alt karedeki bir kare dendrogram ve sağ alt taraftaki renk çubuğuyla birlikte bir kare ısı haritası. hiçbir şey fantezi değil.

Son olarak, daha genel soru: matplotlib'i her zaman eksenleri kare yapmak için zorlamak için genel bir kural/ilke var mıdır? Kare eksenleri istemediğim tek bir durumu düşünemiyorum ama genellikle varsayılan davranış değil. Mümkünse tüm arazileri meydanda zorlamak isterim.

cevap

9

HYRY cevabı çok iyidir ve tüm kredi hak @.

from scipy.cluster.hierarchy import linkage 
from scipy.cluster.hierarchy import dendrogram 
from scipy.spatial.distance import pdist 
import matplotlib 
from matplotlib import pyplot as plt 
import numpy as np 
from numpy import arange 

fig = plt.figure(figsize=(5,7)) 
ax1 = plt.subplot(2, 1, 1) 
cm = matplotlib.cm.Blues 
X = np.random.random([5,5]) 
pmat = pdist(X, "euclidean") 
linkmat = linkage(pmat) 
dendrogram(linkmat) 
x0,x1 = ax1.get_xlim() 
y0,y1 = ax1.get_ylim() 
ax1.set_aspect((x1-x0)/(y1-y0)) 

plt.subplot(2, 1, 2, aspect=1) 
labels = ["a", "b", "c", "d", "e", "f"] 
Y = np.random.random([6,6]) 
plt.xticks(arange(0.5, 7.5, 1)) 
plt.gca().set_xticklabels(labels) 
plt.pcolor(Y) 
plt.colorbar() 

# add a colorbar to the first plot and immediately make it invisible 
cb = plt.colorbar(ax=ax1) 
cb.ax.set_visible(False) 

plt.show() 

code output

13

yönü = "eşit" ekran alanı aynı uzunlukta olacak veri alanı aynı uzunluk ve ortalama fakat bir kare olmayacak şekilde üst ekseninde, x ekseni ve y-ekseni veri aralıkları aynı değildir, .Bu sorunu gidermek için, Xaxis aralığının oranı ve yEkseni aralığına yönünü ayarlayabilirsiniz: Burada

from scipy.cluster.hierarchy import linkage 
from scipy.cluster.hierarchy import dendrogram 
from scipy.spatial.distance import pdist 
import matplotlib 
from matplotlib import pyplot as plt 
import numpy as np 
from numpy import arange 

fig = plt.figure(figsize=(5,7)) 
ax1 = plt.subplot(2, 1, 1) 
cm = matplotlib.cm.Blues 
X = np.random.random([5,5]) 
pmat = pdist(X, "euclidean") 
linkmat = linkage(pmat) 
dendrogram(linkmat) 
x0,x1 = ax1.get_xlim() 
y0,y1 = ax1.get_ylim() 
ax1.set_aspect((x1-x0)/(y1-y0)) 
plt.subplot(2, 1, 2, aspect=1) 
labels = ["a", "b", "c", "d", "e", "f"] 
Y = np.random.random([6,6]) 
plt.xticks(arange(0.5, 7.5, 1)) 
plt.gca().set_xticklabels(labels) 
plt.pcolor(Y) 
plt.colorbar() 

çıktısı: konumu için

enter image description here

bir ColorBarLocator yazmak gerek Colorbar eksenler arasındaki boşluğu ayarlamak ve Col: Sınıf, ped ve genişlik bağımsız değişken, piksel biriminde

  • ped olan obar
  • genişliği: Colorbar

genişliği aşağıdaki kodla plt.colorbar() değiştirin:

class ColorBarLocator(object): 
    def __init__(self, pax, pad=5, width=10): 
     self.pax = pax 
     self.pad = pad 
     self.width = width 

    def __call__(self, ax, renderer): 
     x, y, w, h = self.pax.get_position().bounds 
     fig = self.pax.get_figure() 
     inv_trans = fig.transFigure.inverted() 
     pad, _ = inv_trans.transform([self.pad, 0]) 
     width, _ = inv_trans.transform([self.width, 0]) 
     return [x+w+pad, y, width, h] 

cax = fig.add_axes([0,0,0,0], axes_locator=ColorBarLocator(ax2)) 
plt.colorbar(cax = cax) 

enter image description here

+0

Teşekkür ancak araziler hala düzenli subplots gibi düzenlenmez. Üst ve alt için sınırlayıcı kutular hizalanmamış. Onları sağa sarkan renkle dikey olarak hizalanmasını isterim, senin gibi, ama yanlış hizalanmış gibi. Bu konuda bir fikrin var mı? – user248237dfsf

+1

Cevabı düzenledim, lütfen kontrol et. – HYRY

+0

Cevabınız için teşekkürler - tam olarak doğru çıktı ama kod son derece karmaşık görünüyor! daha kolay bir yolu var mı matplotlib geliştiricilerinden biri gibi, böyle bir şeyi nasıl yazacağınızı bilmek zorundasınız gibi görünüyor, sadece bir renk çubuğu elde etmek için ... – user248237dfsf

0

diğerine eklemek için: Ama güzel kadar kare araziler astar hakkında cevap bitirmek için, yalnızca ilki görünmez hale hem araziler ColorBars sahip olduğunu düşünerek içine matplotlib yanıltabilirsiniz cevaplar, sen .set_aspect bağımsız değişken mutlak değerini almak gerekir: cevap için

x0,x1 = ax1.get_xlim() 
y0,y1 = ax1.get_ylim() 
ax1.set_aspect(abs(x1-x0)/abs(y1-y0)) 
İlgili konular