如何提高网络图的可视化?
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。压缩不可压缩
你的图中有 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。免责声明:我参与了此应用程序的开发。
我尝试在 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。压缩不可压缩
你的图中有 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。免责声明:我参与了此应用程序的开发。