前言
由于来源不同,导致网上公开的网络数据集格式也没有统一规范,在进行科学计算时往往由数据格式的差异导致意想不到的Bug。如果在进行核心计算时处理以上差异不仅耗时耗力,还会增加计算代码量,使得处理逻辑变得复杂,降低计算效率与速度。除了上述弊端外,由于处理格式问题与其余基于复杂网络的科学计算相比,计算量是微不足道的,故而可以先将数据格式处理一致后在进行计算。
本文将基于 http://networkrepository.com/ 上公开的网络以及其格式统一处理为.txt格式,除此外结合本人研究需求,将网络处理为无权无向网,同时只保留最大连通子图。处理后的数据将仅仅保留节点与连边,表示为一条边,分别为源节点何目标节点。
本人已经处理好600多个网络数据集上传,节点数范围20-7000,包括社交网络,生物网络,蛋白质网络,经济网络,交通网络,电力网络等等。需要的读者可以点击下方链接下载使用。
一、环境
Python3
networkx
二、代码
import os
import networkx as nx
import re
# 对图的编号重排
def relabel_graph_nodes(G):
# 所有的节点
all_nodes = list(G.nodes())
if min(all_nodes) == 1 and max(all_nodes) == len(all_nodes):
return G
else:
all_len = len(all_nodes) # 节点数量
# 所有的边
all_exist_edges = all_edges(G)
all_exist_edges.sort()
# 重新构造图
H = nx.Graph()
# 加点
H.add_nodes_from(range(1,all_len+1))
# 加边
for edge in all_exist_edges:
a = all_nodes.index(edge[0])+1
b = all_nodes.index(edge[1])+1
H.add_edge(a,b)
return H
# 对边重排序,保证前小后大
def re_order_edge_list(lre):
li = list()
for i in lre:
try:
a = i[0]
b = i[1]
if a < b:
li.append((a,b))
elif a > b:
li.append((b,a))
else:
pass
except Exception:
pass
return li
# 对图进行预处理
def pre_tackle_nx_graph(G):
# 获取图G的最大连通子图
H = nx.subgraph(G,max(nx.connected_components(G),key=len))
# 对图的编号重排
H = relabel_graph_nodes(H)
return H
# 图中所有已经存在的边
def all_edges(G):
e = G.edges()
lre = re_order_edge_list(e)
return lre
def tacle_data(text):
text_name = text.split("/")[3].replace(".txt","")
# 读取图
with open(text, "r") as f:
res = f.read()
li = res.split('\n')
if "" in li:
li.remove("")
no=0
if '.mtx' in text:
for i in li:
if '%' not in i:
break
else:
no+=1
li = li[no+1:]
if '.edges' in text:
for i in li:
if '%' not in i:
break
else:
no+=1
li = li[no:]
lre = list()
for i in li:
if " " in i:
line = i.split(" ")
if "," in i:
line = i.split(",")
if " " in i:
line = i.split(" ")
try:
a = int(line[0])
b = int(line[1])
if a < b:
lre.append((a,b))
elif a > b:
lre.append((b,a))
elif a == b:
continue
else:
pass
except Exception:
print(text)
exit(0)
print(text_name)
# 去重
lre = list(set(lre))
# 排序
lre.sort()
# 边数
edges = len(lre)
# 节点个数
nodes = list(set([i for j in lre for i in j]))
nodes_len = len(nodes)
# 节点编号从0开始
if min(nodes) != 1:
new_lre = list()
x = 1-min(nodes)
for edge in lre:
new_lre.append([edge[0]+x,edge[1]+x])
return new_lre
# 节点编号从1开始
elif min(nodes) == 1:
return lre
else:
raise Exception
if __name__ == '__main__':
#target = input('input run dir:')
target = "newdata"
# 指定路径下所有的图数据
path = "./freshdata/{}/".format(target)
jobs = os.listdir(path)
obj = "finish/"
path_f = "./freshdata/{}/".format(obj)
dir_class = ['1-100','100-500','500-1000','1000-2000','2000-3000','3000-4000','5000-100000','1000-3000','all']
# 按节点数分类创造文件夹
for i in dir_class:
is_exists = os.path.exists(path_f+i)
if not is_exists:
os.mkdir(path_f+i)
# 对图进行运算
for i in jobs:
try:
filname = i.split(".")[0]
text = path+i
# 重新构造文件名
lre = tacle_data(text)
# 构造networkx 图对象
G_nx = nx.Graph()
G_nx.add_edges_from(lre)
# 对图进行预处理,将不连通的图取其最大连通子图,并对节点重编号
G_nx = pre_tackle_nx_graph(G_nx)
lre = all_edges(G_nx)
edges = len(lre)
nodes = list(set([i for j in lre for i in j]))
nodes_len = len(nodes)
try:
pattern = re.compile("_\d+_\d+\d$")
useless = pattern.search(filname).group()
filname = filname.replace(useless,"")
except Exception as e:
print(e)
for i in dir_class:
if i != "all":
min_d,max_d = i.split("-")
if nodes_len > int(min_d) and nodes_len <= int(max_d):
with open(path_f+'/'+i+'/'+filname+"_"+str(nodes_len)+"_"+str(edges)+".txt", "w") as f:
for i in lre:
f.write(str(i[0])+" "+str(i[1]))
f.write("\n")
else:
with open(path_f+'/'+i+'/'+filname+"_"+str(nodes_len)+"_"+str(edges)+".txt", "w") as f:
for i in lre:
f.write(str(i[0])+" "+str(i[1]))
f.write("\n")
except Exception as e:
print(i,"error")
三、使用说明
- 在这里将以上代码保存为preData.py文件。
- 在与preData.py文件同级目录下新建文件夹freshdata。
- 在freshdata文件夹下建立fiinish与newData文件夹。
- newData文件夹下存放待处理的数据集。
- 返回 preData.py所在目录,并将其执行。
- finish目录下将生成处理好格式的代码,并根据节点数分类
- 处理好的网络数据文件名为:数据集名称_节点数_边数.txt