将距离矩阵可视化为图形

4
我正在进行聚类任务,有一个距离矩阵。我希望将这个距离矩阵可视化为2D图形。请告诉我是否有在线或在R或Python等编程语言中完成此操作的方法。 我的距离矩阵如下所示: enter image description here 我使用了经典多维缩放功能(在R中),并获得了一个看起来像这样的2D图: enter image description here 但是我想要的是一个具有节点和加权边的图形。

@Anony-Mousse:我尝试了答案中提到的很多方法(例如http://vida.io,Python代码片段-都无济于事)。希望我能很快让Python代码运行起来。此外,我正在同时阅读一些与我的工作相关的内容,所以如果你想让我很快更新这篇文章/接受一个答案,那是不可能的。 - Annamalai N
嗯,MDS图是一个不错的起点。然后可以添加Delauney三角剖分或使用其他一些启发式方法来添加边。 - Has QUIT--Anony-Mousse
好的,我明白了,当我能够获取到边缘时,我会更新这个问题。 - Annamalai N
4个回答

11

可能性一

我假定您想要一个二维图,其中节点位置之间的距离与您的表所提供的距离相同。

在Python中,您可以使用networkx进行此类应用程序。一般来说,有许多方法可以实现这一点,记住,它们都只是近似值(因为通常不可能根据它们的成对距离创建点的二维表示),它们是某种应力最小化(或能量最小化)的近似值,试图找到与所提供的“相似”距离具有“合理”的表示。

例如,您可以考虑一个四个点的示例(使用正确的离散度量):

     p1 p2 p3 p4
  ---------------
  p1  0  1  1  1
  p2  1  0  1  1
  p3  1  1  0  1
  p4  1  1  1  0

通常情况下,绘制实际的“图形”是多余的,因为你已经完全连接了它(每一对节点都是相连的),所以只绘制点应该就足够了。

Python示例

import networkx as nx
import numpy as np
import string

dt = [('len', float)]
A = np.array([(0, 0.3, 0.4, 0.7),
               (0.3, 0, 0.9, 0.2),
               (0.4, 0.9, 0, 0.1),
               (0.7, 0.2, 0.1, 0)
               ])*10
A = A.view(dt)

G = nx.from_numpy_matrix(A)
G = nx.relabel_nodes(G, dict(zip(range(len(G.nodes())),string.ascii_uppercase)))    

G = nx.to_agraph(G)

G.node_attr.update(color="red", style="filled")
G.edge_attr.update(color="blue", width="2.0")

G.draw('distances.png', format='png', prog='neato')

在R中,你可以尝试多维缩放

# Classical MDS
# N rows (objects) x p columns (variables)
# each row identified by a unique row name

d <- dist(mydata) # euclidean distances between the rows
fit <- cmdscale(d,eig=TRUE, k=2) # k is the number of dim
fit # view results

# plot solution 
x <- fit$points[,1]
y <- fit$points[,2]
plot(x, y, xlab="Coordinate 1", ylab="Coordinate 2", 
  main="Metric  MDS",    type="n")
text(x, y, labels = row.names(mydata), cex=.7)

可能性2

你只是想绘制带有标签的边缘图

同样,networkx 可以提供帮助:

import networkx as nx   

# Create a graph
G = nx.Graph()

# distances
D = [ [0, 1], [1, 0] ]

labels = {}
for n in range(len(D)):
    for m in range(len(D)-(n+1)):
        G.add_edge(n,n+m+1)
        labels[ (n,n+m+1) ] = str(D[n][n+m+1])

pos=nx.spring_layout(G)

nx.draw(G, pos)
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels,font_size=30)

import pylab as plt
plt.show()

networkx是否与Python 2.7不兼容? 我收到以下错误:(翻译成中文) 文件“test.py”,第16行,在<module>中: G = nx.to_agraph(G) 在“/usr/local/lib/python2.7/dist-packages/networkx/drawing/nx_agraph.py”中的第134行,to_agraph函数出现错误: '(not available for Python3)' - Annamalai N
1
它在Python 2.7上运行良好。尝试安装此函数使用的http://pygraphviz.github.io/。 - lejlot

3

谢谢您的回答,虽然不是我想要的,但看起来很有趣。我想将该矩阵可视化为一个节点和带权边的图形。此外,我在这里找到了一个MDS的R示例实现链接。我会尽快向您更新进展。 - Annamalai N

2
您没有提到您是否需要一个二维图表。我猜想您需要构建一个二维图表,因为您需要用它来进行可视化。但需要注意的是,对于大多数图表来说,这是不可能的。
可能可以做的是从距离矩阵中近似计算出值,例如小的值具有相对较小的边缘,而大的值则具有相对较长的长度。
在所有先前的考虑中,一种选择是使用 graphviz。请查看neato函数。总的来说,您感兴趣的是力导向绘图。请参见wikipedia以获取更多信息。

0
你可以使用d3js力导向图,并配置节点之间的距离。d3js力布局具有一些聚类能力,以分离具有相似距离的节点。以下是一个示例,其中值表示节点之间的距离:

http://vida.io/documents/SyT7DREdQmGSpsBkK

另一种可视化的方法是使用节点之间相同的距离,但不同的线条粗细。在这种情况下,您需要根据数值计算描边宽度:
.style("stroke-width", function(d) { return Math.sqrt(d.value / 50); });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接