在简单Python中重新排序矩阵元素以反映列和行聚类
我想找到一种方法,先对矩阵的行进行聚类,然后再对列进行聚类,接着重新排列矩阵中的数据,以反映这种聚类,最后把所有的结果整合在一起。聚类问题比较简单,制作树状图也不难(比如在这个博客或者在《编程集体智能》中都有介绍)。不过,如何重新排列数据对我来说还是不太清楚。
最终,我希望能用简单的Python(使用任何“标准”库,比如numpy、matplotlib等,但不使用R或其他外部工具)来创建类似下面的图表。
(来源: warwick.ac.uk)
说明
有人问我重新排列是什么意思。当你先对矩阵的行进行聚类,然后对列进行聚类时,矩阵中的每个单元格可以通过在两个树状图中的位置来识别。如果你重新排列原始矩阵的行和列,使得在树状图中彼此接近的元素在矩阵中也变得接近,然后生成热图,数据的聚类关系可能会变得对观众更加明显(就像上面的图一样)。
2 个回答
我知道这个时候说这些有点晚了,不过我根据这个页面上的代码做了一个绘图对象。它已经在pip上注册了,所以你只需要运行下面的命令就可以安装:
pip install pydendroheatmap
你可以在这里查看这个项目的github页面: https://github.com/themantalope/pydendroheatmap
我不太确定自己完全理解,但看起来你是在尝试根据树状图的索引来重新排列数组的每个轴。我猜这意味着在每个分支的划分中有一些比较逻辑。如果是这样的话,这样做可以吗(?):
>>> 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_idxs
和 y_idxs
是树状图的索引。a
是未排序的矩阵。xi
和 yi
是你新的行/列数组索引。a2
是排序后的矩阵,而 x_idxs2
和 y_idxs2
是新的、已排序的树状图索引。这假设在创建树状图时,0
分支的列/行总是相对比 1
分支要大/小。
如果你的 y_idxs
和 x_idxs
不是列表而是 numpy 数组,那么你可以用 np.argsort
以类似的方式来处理。