如何提高网络图的可视化?

How to improve network graph visualization?

我尝试在 python 中使用 networkx 将相邻矩阵转换为图形。 我的 "weighted" 图有大约 8000 个节点和 14000 条边。 有没有很棒的布局形式或其他包,工具可以让我的图表变得更漂亮? 我希望结果是边缘权重越高,节点越近。 这样我就可以分析集群节点了。

networkx 文档中提供的所有布局我都试过了。 我也试过用gephi,还是有点不满足我的理想。 这就是它在 networkx 中的样子。它可以显示所有集群,但对于患有密集恐惧症的人来说,它看起来有点可怕:

这是我用来绘制图表的代码:

G = nx.Graph()
for i in range(10000):
    for j in range(10000):
        if mat[i][j] > 10:
            G.add_edge(a[i], a[j], weight=mat[i][j])
pos = nx.nx_pydot.graphviz_layout(G)
plt.figure(figsize=(8, 8))
plt.axis('off')
nx.draw_networkx(G, pos=pos, with_labels=False, node_size=25, edgecolors='black', edge_color='b')
plt.show()

让我们深入了解一下大图可视化:

根据您的问题,您可以通过三种方式来可视化图表:

  1. 在一个屏幕上绘制整个图形
  2. 在大于一屏的平面上绘制图形
  3. 部分绘制图表或减少绘制元素的数量

我们将一一回顾这些方式:

1。压缩不可压缩

你的图中有 8000 个节点和 14000 条边。假设您只需要绘制没有边的节点。因此,对于普通的全高清显示器,您将拥有:

每个节点

1920 * 1080 / 8000 = 259 像素。它是:

sqrt(259) = 17

A 17×17 像素。节点,如果您要用节点平铺整个显示。如果你想绘制节点标签,你将有:

17 - 1 * 2 (outer node borders) - 1 * 2 (inner node borders) = 13×13平方。最小的字体(我不会谈论 esoteric 字体)有 3×3(+1) 大小,因此每个节点可以存储不超过 9 个字符。

看起来像这样:

而且我们还没有画出图的边!如果我们想这样做,我们将使用:

每个图形元素

1920 * 1080 / (8000 + 14000) = 94 个像素,并且:

sqrt(94) = 9.7 - 9×9 像素。节点,因此几乎不可能在它们上面贴上简单的标签。

我认为现在很明显,单个屏幕上的整个图形总是看起来一团糟。因此,以这种方式绘制图形不是一种选择。

2。展开不可展开

如果不能在一个屏幕上绘制图表,我们可以绞尽脑汁想出一个办法——在多个屏幕上绘制!我们可以通过两种方式做到这一点:

  • 使用 matplotlib
  • 使用 graphviz

在 matplotlib 案例中,我们创建了一个非常大的图形(带有 figsize 参数),然后将图形导入图片(带有 plt.savefig):

import networkx as nx 
import matplotlib.pyplot as plt 

fig = plt.figure(figsize=(40, 40)) 
G = nx.fast_gnp_random_graph(300, 0.02, seed=1337) 
nx.draw(G, node_size=30) 
plt.axis('equal') 
plt.show() 
fig.savefig('waka.svg') 

这样我们就得到了一张大矢量图(这里是其中的一小部分):

在这种情况下,我们可以使用 networkx 中可用的任何图形布局。

另一种方法是使用 Graphviz 外部库来绘制我们的图形。老实说,在这种情况下,networkx 只会将图形转换为 .dot 文件并将其发送到 Graphviz。主要缺点是您无法控制 Graphviz 绘制图形的方式。不过版面设计的还不错,效果还可以吧

使用此 Python 代码生成 .dot 文件:

import networkx as nx 

G = nx.fast_gnp_random_graph(300, 0.02, seed=1337) 
nx.nx_agraph.write_dot(G, './waka.dot')

然后使用 Graphviz:

dot -Tsvg waka.dot >waka.svg

或对于无向图:

neato -Tsvg waka.dot -Goverlap=false >waka.svg

所以结果图会是这样的(这里也是整张图的一小部分):

Graphviz 有大量不同的选项,因此您可以根据自己的意愿转换图表。

3。切不可切

在你的图表中,你有一个巨大的连接组件(GCC)和许多小子图。整个图片大约是580×580大小,GCC大约是290×290大小所以GCC使用:

(290 × 290) ÷ (580 × 580) × 100 = 25% 个 canvas。如果你只保留 GCC,你将有 4 倍的 space 可以抽奖!在这种情况下,您可以在另一幅图像上绘制另一个连通分量。

您只能使用如下代码保留 GCC:

import networkx as nx 

G = nx.fast_gnp_random_graph(300, 0.01, seed=1337)
gcc = max(nx.connected_components(G), key=lambda x: len(x))
H = G.subgraph(gcc)
nx.draw(G, node_size=30, node_color='red')

将绘制原图:

最后一行:

nx.draw(H, node_size=30, node_color='red')

它将只绘制 GCC:


P.S.

您还可以尝试用图表做什么:

  • 集群化节点
  • 使用节点大小(PageRank 等)
  • 玩转边缘颜色
  • 不画边,保持布局
  • 哭泣(以防我的回答对你一点帮助都没有)

另一种改进可视化的方法是在 3D 中绘图。这有助于消除连接区域的歧义,因为存在额外的自由度。可以做到这一点的工具是 Graphia。免责声明:我参与了此应用程序的开发。