2012-08-09 3 views
11

저는 사각 축을 유지하면서 하나의 서브 플롯에서 덴 드로 그램과 다른 서브 플롯에서 히트 맵을 사용하여 간단한 서브 플롯을 만들려고합니다.히트 맵을 사용하여 matplotlib에서 사각형 서브 그림을 만드는 방법은 무엇입니까?

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

이 다음 산출 :

enter image description here

을하지만 문제는 축이 사각형이 있는지, 그리고 년 Colorbar 두 번째 부가 적 줄거리의 일부로 간주되어 나는 다음 시도하십시오. 그 대신 줄거리 바깥에 매달려 있고 dendrogram 상자와 heatmap 상자가 사각형이면서 서로 (즉 동일한 크기) 정렬되도록하십시오.

사각형 축을 얻기 위해 aspect='equal'을 사용해 보았습니다. ...

enter image description here

내가 대신 aspect='equal'의 각 부가 적 줄거리 후 plt.axis('equal')를 사용하려고하면, 그것은 이상하게도 사각형 히트 맵이 아닌 그 경계 상자를 문서에서 알 수 있듯이 subplot를 호출하지만이주는 플롯을 파괴 (아래 참조), dendrogram을 완전히 파괴하고 또한 xtick 레이블의 정렬을 엉망으로 만들 때 .... -이 혼란에 상승을 제공 :

enter image description here

방법

이 고정 될 수 있는가? 요약하면, 나는 아주 간단한 것을 그려보기 위해 노력하고있다 : 상단 서브 플롯에 사각형 dendrogram, 하단에 subplot에 사각형 히트 맵, 오른쪽에 컬러 바가있다. 아무것도 공상 아니야.

마지막으로, 더 일반적인 질문 : matplotlib을 강제로 수행하는 데 따르는 일반적인 규칙/원칙이 있습니까 항상 축을 사각형으로 만드시겠습니까? 사각형 축을 원하지 않는 단일 사례를 생각할 수는 없지만 일반적으로 기본 동작은 아닙니다. 가능하다면 모든 플롯을 정사각형으로 만들고 싶습니다.

답변

9

을 HYRY의 대답은 매우 좋은 모든 신용을받을 권리가 @.

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

aspect = "같음"은 데이터 공간에서 동일한 길이가 화면 공간에서 동일한 길이가된다는 것을 의미하지만 상단 도끼에서 xaxis와 yaxis의 데이터 범위는 동일하지 않으므로 사각형이 아닙니다 .이 문제를 해결하려면, 당신은 X- 축 범위의 비율과 y 축 범위로 화면을 설정할 수 있습니다 여기에

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

하면 출력 : 위치

enter image description here

우리가 ColorBarLocator 쓰기 필요 년 Colorbar 축 사이의 간격을 설정하고는 대장균이다 : 클래스 패드 폭 인수는, 화소 단위

  • 패드이다 obar
  • 다음 년 Colorbar

의 폭은 다음 코드로 plt.colorbar() 대체 :

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

답장을 보내 주셔서 감사합니다. 그러나 귀하의 플롯은 여전히 ​​정규 서브 플로트처럼 정렬되지 않습니다. 위쪽과 아래쪽의 경계 상자가 정렬되지 않습니다. 나는 그들이 오른쪽으로 매달려있는 색상으로 수직으로 정렬되기를 바랍니다. 당신이 가지고있는 것처럼 보이지만 어긋나지는 않습니다. 이것에 대한 아이디어가 있습니까? – user248237dfsf

+1

답변을 편집했습니다. 확인하십시오. – HYRY

+0

답장을 보내 주셔서 감사합니다. 정확히 정확한 결과물이지만 코드는 대단히 복잡해 보입니다! 더 쉬운 방법이 있습니까? 당신이 matplotlib 개발자 중 한 명일 필요가있는 것처럼 보입니다.이 같은 것을 쓰는 방법을 알기 만하면됩니다. – user248237dfsf

0

다른 추가하려면 : 그러나 멋지게 제곱 플롯을 안감에 대한 답을 마무리하기 위해, 당신은 첫 번째 사람이 보이지 않게 두 플롯이 colorbars을 가지고 생각으로하기 matplotlib 속일 수 인수의 절대 값을 .set_aspect으로 가져 가야합니다.

x0,x1 = ax1.get_xlim() 
y0,y1 = ax1.get_ylim() 
ax1.set_aspect(abs(x1-x0)/abs(y1-y0)) 
관련 문제