我需要快速创建一个大型 NetworkX Graph,其中的数据来自对某个数据库的查询,返回大量数据。我一一添加节点和边会慢得离谱。有没有更快的方法?
在经历了自己出乎意料的慢网络创建之后,我做了一些测试,发现了一个令人惊讶的创建方法,它为我加快了很多速度。
在循环数据之前,创建一个要添加的空边列表:
edgesToAdd = []
还创建一个字典来保存节点属性
nodeDict = {}
然后循环遍历数据并以正确的格式将边添加到边列表中:
edgesToAdd.append([sourceNode, targetNode, attrDict])
还要遍历节点并将节点属性添加到该字典中。
for index,nodeID in enumerate(newNodeIDs):
nodeDict[nodeID] = {}
nodeDict[nodeID]['attr1'] = 'stringVal'
nodeDict[nodeID]['attr1'] = numval
然后在处理完所有数据后,循环遍历该边列表以添加属性。
for n1,n2,attr in edgesToAdd:
G.add_edge(n1, n2)
nx.set_edge_attributes(G, {(n1, n2): attr})`
如果所有节点都是边的结束节点,那么上面已经创建了节点,所以只需设置节点属性即可。
nx.set_node_attributes(G, nodeDict)
我有限的测试表明
G.add_nodes_from
非常慢,但设置属性很快。 我还发现(违反直觉)循环遍历列表来添加边,然后添加其属性,比在边创建期间添加属性稍快,并且两者都比G.add_edges_from
更快。
对于我的网络的测试部分,运行时间从使用标准方法(Infiniticity 推荐的方法)的1.2 分钟变为使用这些基本解决方法的3.3 秒。
此过程假设所有节点都附加到某个边缘,但如果您有松散的节点,那么您可能会发现循环遍历列表并一次添加一个节点比使用内置 NetworkX 方法(违反直觉)更快专门为此目的而设计。