使用NetworkX进行二分图投影并写入CSV - 如何加速处理大型文件的写入

0 投票
1 回答
1880 浏览
提问于 2025-04-18 14:22

我有一个非常大的文件(300万行),每一行都是一个人和事件之间的关系。最终,我想把这个双向网络转换成一个单向的、带权重的网络,并把它写入一个CSV文件。我正在使用NetworkX,并且我在一个小得多的样本数据集上测试过我的代码,效果很好。但是,当我用实际数据集时,我的电脑内存用满了,转啊转就是不见进展。

我在一台内存为32GB的AWS EC2机器上工作。

经过一些样本测试,我很确定问题出在最后一步,也就是图形被转换后写入CSV文件时。我尝试把文件分成小块,但这样就出现了缺少边或者边的权重加不对的问题。不过,我觉得更好的解决办法是找到一种方法,加快将转换后的图写入CSV的速度。

关于原始数据的更多信息:有些事件只有1个人参加,而其他事件则有5000人参加。因此,当双向网络转换成单向网络时,会产生大量的边(我预测大约有5000万条)。

使用NetworkX将双向网络转换并写入CSV的代码

# import modules
import time
import csv
import networkx as nx
from networkx.algorithms import bipartite

startTime = datetime.datetime.now()

# rename files
infile = 'bipartite_network.csv'
name_outfile = infile.replace('.csv', '_nameFolded.csv.')
print 'Files renamed at: ' + str(datetime.datetime.now() - startTime)

# load CSV into a dict
with open(infile, 'rb') as csv_file:
    rawData = list(csv.DictReader(csv_file))
print 'Files loaded at: ' + str(datetime.datetime.now() - startTime)

# create edgelist for Name -x- Event relationships
edgelist = []
for i in rawData:
    edgelist.append(
    (i['Event'],
     i['Name'])    
    )
print 'Bipartite edgelist created at: ' + str(datetime.datetime.now() - startTime)

# deduplicate edgelist
edgelist = sorted(set(edgelist))
print 'Bipartite edgelist deduplicated at: ' + str(datetime.datetime.now() - startTime)

# create a unique list of Name and Event for nodes
Event = sorted(set([i['Event'] for i in rawData]))
Name = sorted(set([i['Name'] for i in rawData]))
print 'Node entities deduplicated at: ' + str(datetime.datetime.now() - startTime)

# add nodes and edges to a graph
B = nx.Graph()
B.add_nodes_from(Event, bipartite=0)
B.add_nodes_from(Name, bipartite=1)
B.add_edges_from(edgelist)
print 'Bipartite graph created at: ' + str(datetime.datetime.now() - startTime)

# create bipartite projection graph
name_nodes, event_nodes = bipartite.sets(B)
event_nodes = set(n for n,d in B.nodes(data=True) if d['bipartite']==0)
name_nodes = set(B) - event_nodes
name_graph = bipartite.weighted_projected_graph(B, name_nodes)
print 'Single-mode projected graph created at: ' + str(datetime.datetime.now() - startTime)

# write graph to CSV
nx.write_weighted_edgelist(name_graph, name_outfile, delimiter=',')
print 'Single-mode weighted edgelist to CSV: ' + str(datetime.datetime.now() -    startTime)

endTime = datetime.datetime.now()
print 'Run time: ' + str(endTime - startTime)

使用Pandas写入转换后的边列表,但边权重缺失?

我考虑过用pandasname_graph写入CSV。这会是加快写入CSV过程的一个好选择吗?

import pandas as pd
df = pd.DataFrame(name_graph.edges(data=True))
df.to_csv('foldedNetwork.csv')

1 个回答

1

这是我在networkx-discuss邮件列表上提出的建议:

import networkx as nx

B = nx.Graph()
B.add_edge('a',1)
B.add_edge('a',2)
B.add_edge('b',1)
B.add_edge('b',2)
B.add_edge('b',3)
B.add_edge('c',3)

nodes = ['a','b','c']
seen = set()
for u in nodes:
#    seen=set([u]) # print both u-v, and v-u
    seen.add(u) # don't print v-u
    unbrs = set(B[u])
    nbrs2 = set((n for nbr in unbrs for n in B[nbr])) - seen
    for v in nbrs2:
        vnbrs = set(B[v])
        common = unbrs & vnbrs
        weight = len(common)
        print("%s, %s, %d"%(u,v,weight))

撰写回答