在同一个图上绘制两个距离矩阵? [英] Plotting two distance matrices together on same plot?

查看:33
本文介绍了在同一个图上绘制两个距离矩阵?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从两个不同的距离矩阵创建树状图并进行比较.我使用了代码

这是我的代码:

from sklearn 导入预处理从 sklearn.neighbors 导入 DistanceMetric将熊猫导入为 pd将 numpy 导入为 np从 ete3 导入树从 sklearn.metrics.pairwise 导入 cosine_similarity从 sklearn.metrics.pairwise 导入 cosine_distances进口scipy导入pylab将 scipy.cluster.hierarchy 导入为 sch将 scipy.spatial.distance 导入为 sd随机导入#g[n] 是包含数据点的一维数组g1 = random.sample(range(30), 5)g2 = random.sample(range(30), 5)g3 = random.sample(range(30), 5)g4 = random.sample(range(30), 5)g5 = random.sample(range(30), 5)g1 = np.array(g1)g2 = np.array(g2)g3 = np.array(g3)g4 = np.array(g4)g5 = np.array(g5)X = (g1,g2,g3,g4,g5)#欧氏和余弦的比较#######################################距离C = cosine_distances(X)dist = DistanceMetric.get_metric('欧几里得')距离E = dist.pairwise(X)##############################################################################Plots######################################################################### 计算并绘制第一个树状图.图 = pylab.figure(figsize=(8,8))ax1 = fig.add_axes([0.09,0.1,0.2,0.6])Y = sch.average(sd.squareform(distanceC))Z1 = sch.dendrogram(Y,orientation='right')ax1.set_xticks([])ax1.set_yticks([])# 计算并绘制第二个树状图.ax2 = fig.add_axes([0.3,0.71,0.6,0.2])Y = sch.average(sd.squareform(distanceE))Z2 = sch.dendrogram(Y)ax2.set_xticks([])ax2.set_yticks([])# 绘制距离矩阵.axmatrix = fig.add_axes([0.3,0.1,0.6,0.6])idx1 = Z1['叶子']idx2 = Z2['叶子']距离 = 距离[idx1,:]距离 = 距离[:,idx2]im = axmatrix.matshow(distance, aspect='auto', origin='lower', cmap=pylab.cm.YlGnBu)axmatrix.set_xticks([])axmatrix.set_yticks([])# 绘制颜色条.axcolor = fig.add_axes([0.91,0.1,0.02,0.6])pylab.colorbar(im, cax=axcolor)图.show()fig.savefig('树状图.png')#############################################################################

解决方案

没有内置方法来绘制由三角形组成的图像,将像素切成两半.

因此需要构建一些自定义热图.这可以使用三角形的 PolyCollection 来完成.在下面的解决方案中,一个函数围绕原点创建三角形的点,根据需要旋转它们,并应用偏移.循环数组允许为每个点创建一个三角形.最后,所有这些三角形都被收集到一个 PolyCollection 中.

然后,您可以决定对数组之一使用普通的 imshowmatshow 图,并在其顶部使用自定义三角形矩阵.

将 matplotlib.pyplot 导入为 plt导入 matplotlib.collections 作为集合将 numpy 导入为 npdef triatpos(pos=(0,0), rot=0):r = np.array([[-1,-1],[1,-1],[1,1],[-1,-1]])*.5rm = [[np.cos(np.deg2rad(rot)), -np.sin(np.deg2rad(rot))],[np.sin(np.deg2rad(rot)),np.cos(np.deg2rad(rot))]]r = np.dot(rm, r.T).Tr[:,0] += pos[0]r[:,1] += pos[1]返回def triamatrix(a, ax, rot=0, cmap=plt.cm.viridis, **kwargs):段 = []对于范围内的 i(a.shape[0]):对于范围内的 j(a.shape[1]):segs.append(triatpos((j,i), rot=rot) )col = collections.PolyCollection(segs, cmap=cmap, **kwargs)col.set_array(a.flatten())ax.add_collection(col)返回列A,B = np.meshgrid(range(5), range(4))B*=4图, ax=plt.subplots()im1 = ax.imshow(A)im2 = triamatrix(B, ax, rot=90, cmap="Reds")fig.colorbar(im1, ax=ax, )fig.colorbar(im2, ax=ax, )plt.show()

当然,同样可以使用其中的两个三角形矩阵

im1 = triamatrix(A, ax, rot=0, cmap="Blues")im2 = triamatrix(B, ax, rot=180, cmap="Reds")ax.set_xlim(-.5,A.shape[1]-.5)ax.set_ylim(-.5,A.shape[0]-.5)

这还需要手动设置轴限制.

I'm trying to create dendrograms from two different distance matrices and compare them. I used the code here as a starting point, but the problem is since I'm using two different matrices but same clustering method, I need to plot two different matrices together for a comparative analysis. I was wondering if it is possible to separate to halves of each square/node diagonally to show two different distance matrices.

This image represents the result which I'm targeting for:

Here is my code:

from sklearn import preprocessing
from sklearn.neighbors import DistanceMetric 
import pandas as pd
import numpy as np
from ete3 import Tree
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.metrics.pairwise import cosine_distances
import scipy
import pylab
import scipy.cluster.hierarchy as sch
import scipy.spatial.distance as sd 
import random
#g[n] is a one dimensional array containing datapoints
g1 = random.sample(range(30), 5)
g2 = random.sample(range(30), 5)
g3 = random.sample(range(30), 5)
g4 = random.sample(range(30), 5)
g5 = random.sample(range(30), 5)
g1 = np.array(g1)
g2 = np.array(g2)
g3 = np.array(g3)
g4 = np.array(g4)
g5 = np.array(g5)
X = (g1,g2,g3,g4,g5)
#Comparing between euclidean and cosine###########################################
distanceC = cosine_distances(X)
dist = DistanceMetric.get_metric('euclidean')
distanceE = dist.pairwise(X)
##################################################################################

#Plots############################################################################

# Compute and plot first dendrogram.
fig = pylab.figure(figsize=(8,8))
ax1 = fig.add_axes([0.09,0.1,0.2,0.6])
Y = sch.average(sd.squareform(distanceC))
Z1 = sch.dendrogram(Y, orientation='right')
ax1.set_xticks([])
ax1.set_yticks([])

# Compute and plot second dendrogram.
ax2 = fig.add_axes([0.3,0.71,0.6,0.2])
Y = sch.average(sd.squareform(distanceE))
Z2 = sch.dendrogram(Y)
ax2.set_xticks([])
ax2.set_yticks([])

# Plot distance matrix.
axmatrix = fig.add_axes([0.3,0.1,0.6,0.6])
idx1 = Z1['leaves']
idx2 = Z2['leaves']
distance = distance[idx1,:]
distance = distance[:,idx2]
im = axmatrix.matshow(distance, aspect='auto', origin='lower', cmap=pylab.cm.YlGnBu)
axmatrix.set_xticks([])
axmatrix.set_yticks([])

# Plot colorbar.
axcolor = fig.add_axes([0.91,0.1,0.02,0.6])
pylab.colorbar(im, cax=axcolor)
fig.show()
fig.savefig('dendrogram.png')
##################################################################################

解决方案

There is no built-in method to draw an image consisting of triangles, cutting the pixels in half.

So one would need to build some custom heatmap. This could be done using a PolyCollection of triangles. In the solution below a function creates the points of a triangle around the origin, rotates them if needed, and applies an offset. Looping over the array allows to create a triangle for each point. Finally all those triangles are collected into a PolyCollection.

You may then decide to use a normal imshow or matshow plot for one of the arrays and the custom triangle matrix on top of it.

import matplotlib.pyplot as plt
import matplotlib.collections as collections
import numpy as np

def triatpos(pos=(0,0), rot=0):
    r = np.array([[-1,-1],[1,-1],[1,1],[-1,-1]])*.5
    rm = [[np.cos(np.deg2rad(rot)), -np.sin(np.deg2rad(rot))],
           [np.sin(np.deg2rad(rot)),np.cos(np.deg2rad(rot)) ] ]
    r = np.dot(rm, r.T).T
    r[:,0] += pos[0]
    r[:,1] += pos[1]
    return r

def triamatrix(a, ax, rot=0, cmap=plt.cm.viridis, **kwargs):
    segs = []
    for i in range(a.shape[0]):
        for j in range(a.shape[1]):
            segs.append(triatpos((j,i), rot=rot) )
    col = collections.PolyCollection(segs, cmap=cmap, **kwargs)
    col.set_array(a.flatten())
    ax.add_collection(col)
    return col


A,B = np.meshgrid(range(5), range(4))
B*=4

fig, ax=plt.subplots()
im1 = ax.imshow(A)
im2 = triamatrix(B, ax, rot=90, cmap="Reds")

fig.colorbar(im1, ax=ax, )
fig.colorbar(im2, ax=ax, )

plt.show()

Of course it would be equally possible to use two of those triangle matrices

im1 = triamatrix(A, ax, rot=0, cmap="Blues")
im2 = triamatrix(B, ax, rot=180, cmap="Reds")
ax.set_xlim(-.5,A.shape[1]-.5)
ax.set_ylim(-.5,A.shape[0]-.5)

which would also require to set the axis limits manually.

这篇关于在同一个图上绘制两个距离矩阵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆