重新排序矩阵元素以反映朴素python中的列和行聚类

Posted

技术标签:

【中文标题】重新排序矩阵元素以反映朴素python中的列和行聚类【英文标题】:Reordering matrix elements to reflect column and row clustering in naiive python 【发布时间】:2011-01-28 04:26:29 【问题描述】:

我正在寻找一种在矩阵行和列上分别执行聚类的方法,重新排序矩阵中的数据以反映聚类并将它们放在一起。聚类问题很容易解决,树状图的创建也很容易解决(例如在this blog 或"Programming collective intelligence" 中)。但是,我仍然不清楚如何重新排序数据。

最终,我正在寻找一种使用朴素 Python(使用任何“标准”库,如 numpy、matplotlib 等,但没有 using R 或其他外部工具)创建类似于以下图形的方法。

(来源:warwick.ac.uk)

澄清

有人问我重新排序是什么意思。当您首先按矩阵行,然后按其列对矩阵中的数据进行聚类时,可以通过两个树状图中的位置来识别每个矩阵单元。如果对原始矩阵的行和列重新排序,使树状图中彼此接近的元素在矩阵中彼此接近,然后生成热图,则数据的聚类对查看者可能会变得明显(如上图)

【问题讨论】:

重新排序是什么意思?用另一个 n 交换 n 相邻行/列? 在处理矩阵时,您肯定想使用 numpy / scipy。 Matplotlib 也很好地模仿了 Matlab。这是一个交易:如果您可以在 Matlab 中执行此操作,您也可以在 scipy 中执行此操作(如果存在细微的语法差异)。 哦,为漂亮的照片 +1 ;-) 我刚把这个放到github上:github.com/WarrenWeckesser/heatmapcluster 【参考方案1】:

请参阅我的recent answer,下面部分复制到this related question。

import scipy
import pylab
import scipy.cluster.hierarchy as sch

# Generate features and distance matrix.
x = scipy.rand(40)
D = scipy.zeros([40,40])
for i in range(40):
    for j in range(40):
        D[i,j] = abs(x[i] - x[j])

# Compute and plot dendrogram.
fig = pylab.figure()
axdendro = fig.add_axes([0.09,0.1,0.2,0.8])
Y = sch.linkage(D, method='centroid')
Z = sch.dendrogram(Y, orientation='right')
axdendro.set_xticks([])
axdendro.set_yticks([])

# Plot distance matrix.
axmatrix = fig.add_axes([0.3,0.1,0.6,0.8])
index = Z['leaves']
D = D[index,:]
D = D[:,index]
im = axmatrix.matshow(D, aspect='auto', origin='lower')
axmatrix.set_xticks([])
axmatrix.set_yticks([])

# Plot colorbar.
axcolor = fig.add_axes([0.91,0.1,0.02,0.8])
pylab.colorbar(im, cax=axcolor)

# Display and save figure.
fig.show()
fig.savefig('dendrogram.png')

(来源:stevetjoa.com)

【讨论】:

哇,不错的解决方案。你让 matplotlib 看起来很简单,我认为这是一项壮举。但是,如何将标签添加到 x 和 y 轴?是否需要使用 twinx 和 twiny,或者有没有更直接的方法。 谢谢。我喜欢 matplotlib 并且经常使用它。 iPython 帮助您进一步探索 matplotlib 和 pylab。要将标签添加到距离矩阵的轴(如图中心),您可以使用set_xticksset_xticklabels。见matplotlib.sourceforge.net/api/…【参考方案2】:

我不确定是否完全理解,但您似乎正在尝试根据各种树状图索引重新索引数组的每个轴。我想这是假设在每个分支描述中都有一些比较逻辑。如果是这种情况,那么这会起作用吗(?):

>>> x_idxs = [(0,1,0,0),(0,1,1,1),(0,1,1),(0,0,1),(1,1,1,1),(0,0,0,0)]
>>> y_idxs = [(1,1),(0,1),(1,0),(0,0)]
>>> a = np.random.random((len(x_idxs),len(y_idxs)))
>>> x_idxs2, xi = zip(*sorted(zip(x_idxs,range(len(x_idxs)))))
>>> y_idxs2, yi = zip(*sorted(zip(y_idxs,range(len(y_idxs)))))
>>> a2 = a[xi,:][:,yi]

x_idxsy_idxs 是树状图索引。 a 是未排序的矩阵。 xiyi 是您的新行/列数组索引。 a2 是排序矩阵,而 x_idxs2y_idxs2 是新的排序树状图索引。这假设在创建树状图时,0 分支列/行总是相对大于/小于1 分支。

如果您的 y_idxs 和 x_idxs 不是列表而是 numpy 数组,那么您可以以类似的方式使用 np.argsort

【讨论】:

"zip(*sorted..." 中的 * 到底是做什么的? 每当我看到zip(*,我都会想到“转置”。解包使用*见这里:docs.python.org/tutorial/… 在这里进行更多讨论:***.com/questions/19339/…【参考方案3】:

我知道这对游戏来说已经很晚了,但我根据本页帖子中的代码制作了一个绘图对象。它是在 pip 上注册的,所以要安装你只需要调用

pip install pydendroheatmap

在此处查看项目的 github 页面:https://github.com/themantalope/pydendroheatmap

【讨论】:

以上是关于重新排序矩阵元素以反映朴素python中的列和行聚类的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从 python 列表中的列和行写入 csv 文件?

切换数据框中的列和行,并在单独的列标题下列出观察结果以执行 Anova:单因素

列和行索引高于 SKTileMapNode 中的列和行数

Pandas:DataFrame数据的更改插入新增的列和行

二维数组中的列和行?

Pandas列表的列,通过迭代(选择)三列的每个列表元素作为新列和行来创建多列[重复]