读写NetworkX图对象

15

我正在处理一个拥有数亿个节点的超大型NetworkX图形对象,希望能够将其写入文件以避免占用所有计算机内存。但是,我需要不断地搜索现有节点、更新边缘等。

有没有好的解决方案?我不确定这将如何与http://networkx.lanl.gov/reference/readwrite.html上提供的任何文件格式一起使用。

我所能想到的唯一解决方案是将每个节点存储为单独的文件,并在文件系统中引用其他节点 - 这样,打开一个节点进行检查就不会超载内存。是否有一个现有的大数据文件系统(例如PyTables)可以做到这一点,而不需要自己编写模板代码?

3个回答

26

首先尝试使用pickle,它专门用于序列化任意对象。

下面是创建一个DiGraph并将其序列化到文件的示例:

import pickle
import networkx as nx

dg = nx.DiGraph()
dg.add_edge('a','b')
dg.add_edge('a','c')
pickle.dump(dg, open('/tmp/graph.txt', 'w'))

从文件中加载 DiGraph 的示例:

import pickle
import networkx as nx

dg = pickle.load(open('/tmp/graph.txt'))
print dg.edges()

输出:

[('a', 'c'), ('a', 'b')]
如果这还不够高效,我建议编写自己的序列化程序来序列化:
1.边缘 2.节点(如果一个节点与没有边相交)
请注意,在可能的情况下使用列表推导式可能更加高效(而不是标准for循环)。
如果这仍然不够高效,我会在Python中调用C ++例程: http://docs.python.org/extending/extending.html

2
+1 Pickle 是个很棒的东西,以前从没听说过,谢谢! - Eduardo
1
Pickle 为对象生成巨大的文件,如果这已经是一个庞大的网络,那么 pickle 几乎肯定不会起作用。但它是一个很棒且未被充分利用的包,有许多其他优点! - LuisZaman
@LuisZaman 我明白你的意思。在这种情况下,我会手动序列化边和节点(如所描述)。但如果图已经在内存中,如果pickle无法适应磁盘空间,我会非常惊讶。 - user
1
首先使用cPickle,它更快。其次,使用HIGHEST_PROTOCOL。这将以更高效的二进制格式保存它。 - Maarten
1
@ericmjl 不错的问题:会的。序列化文件中的一行指定了对象类型(对于提供的示例,该行说(cnetworkx.classes.digraph))。 - user
显示剩余5条评论

4
如果您已经将其构建为NetworkX图,则它已经在内存中。对于这样大的图,我的猜测是您将不得不采用类似于您提出的分别使用文件的方法。但是,我会使用数据库来存储每个节点及其节点之间的多对多连接,而不是使用单独的文件。换句话说,您将拥有一个节点表和一个边表,然后要查询特定节点的邻居,您只需查询任何具有该特定节点的边即可。这应该很快,但我不确定是否能够利用NetworkX的分析函数而不先在内存中构建整个网络。

谢谢Luis。实际上我是在数据库中存储数据。然而,查询节点以获取邻居的操作非常昂贵。我只能想象Google的服务器是什么样子的... - ejang
如果图已经在RAM中,那么为什么序列化会成为问题呢?(磁盘空间比RAM便宜)或者NetworkX是否有某种内部方法来压缩表示,并且在序列化期间会膨胀?我很好奇。 - user
我认为问题的焦点不在于序列化,而在于将其保存在一个能够允许高效查询的结构中。这就是我提出使用数据库的建议所在。 - LuisZaman

0

我忘记了我最初来StackOverflow解决的问题是什么,但我偶然发现了这个问题(虽然晚了将近十年!),我可以推荐Grand,这是一个类似于networkx的库,我们编写它来解决这个问题:

之前

import networkx as nx

g = nx.DiGraph()
g.add_edge("A", "B")
print(len(g.edges()))

之后

import grand
from grand.backends import SQLBackend # or choose another!

g = grand.Graph(backend=SQLBackend())
g.nx.add_edge("A", "B")
print(len(g.nx.edges()))

API与NetworkX相同,但数据存储在SQL、DynamoDB等中。


这段代码能否“写入文件”?并且能否“从文件读取”? - PatrickT
如果您使用基于文件的后端,它可以实现这一点。它还可以读写数据库或内存存储! - j6m8

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