我以CSV格式设置的样本数据如下所示。
无向图有90个节点用数字{10,11,12 .... 99}表示 其权重边缘定义如下。
[样本数据]
node1 node2 weight
23 89 34.9 (i.e. there is an edge between node 23 and 89 with weight 34.9)
75 14 28.5
so on....
我想以网络形式表示这一点。表示它的有效方法是什么(例如Gephi,networkx等)。边缘的厚度应代表边缘重量。
答案 0 :(得分:6)
使用networkx,您可以添加带属性的边
import networkx as nx
G = nx.Graph()
G.add_edge(23, 89, weight=34.9)
G.add_edge(75, 14, weight=28.5)
答案 1 :(得分:5)
如果您有大型csv,我建议您使用pandas
作为任务的I / O部分。 networkx
有一种有用的方法可以与名为from_pandas_dataframe
的pandas
进行交互。假设您的数据采用上述格式的csv,此命令应该适用于您:
df = pd.read_csv('path/to/file.csv', columns=['node1', 'node2', 'weight'])
但是对于演示,我将在你的要求中使用10个随机边缘(你不需要导入numpy
,我只是用它来生成随机数):
import matplotlib as plt
import networkx as nx
import pandas as pd
#Generate Random edges and weights
import numpy as np
np.random.seed(0) # for reproducibility
w = np.random.rand(10) # weights 0-1
node1 = np.random.randint(10,19, (10)) # I used 10-19 for demo
node2 = np.random.randint(10,19, (10))
df = pd.DataFrame({'node1': node1, 'node2': node2, 'weight': w}, index=range(10))
上一个块中的所有内容都应生成与pd.read_csv
命令相同的内容。导致此DataFrame,df
:
node1 node2 weight
0 16 13 0.548814
1 17 15 0.715189
2 17 10 0.602763
3 18 12 0.544883
4 11 13 0.423655
5 15 18 0.645894
6 18 11 0.437587
7 14 13 0.891773
8 13 13 0.963663
9 10 13 0.383442
使用from_pandas_dataframe
初始化MultiGraph
。这假设您将有多个边连接到一个节点(未在OP中指定)。要使用此方法,您必须在networkx
文件中轻松更改convert_matrix.py
源代码,实施here(这是一个简单的错误)。
MG = nx.from_pandas_dataframe(df,
'node1',
'node2',
edge_attr='weight',
create_using=nx.MultiGraph()
)
这会生成您的MultiGraph,您可以使用draw
:
positions = nx.spring_layout(MG) # saves the positions of the nodes on the visualization
# pass positions and set hold=True
nx.draw(MG, pos=positions, hold=True, with_labels=True, node_size=1000, font_size=16)
详细说明:
positions
是一个字典,其中每个节点都是一个键,值是图表上的一个位置。我将描述为什么我们在下面存储positions
。通用draw
将使用指定MG
处的节点绘制MultiGraph实例positions
。但是,正如您所看到的那样,边缘宽度相同:
但是你拥有增加重量所需的一切。首先将权重放入名为weights
的列表中。使用edges
通过每条边迭代(使用列表理解),我们可以提取权重。我选择乘以5
,因为它看起来最干净:
weights = [w[2]['weight']*5 for w in MG.edges(data=True)]
最后我们将使用draw_networkx_edges
,它只绘制图形的边缘(没有节点)。由于我们有positions
个节点,并且我们设置了hold=True
,因此我们可以在之前的可视化之上绘制加权边。
nx.draw_networkx_edges(MG, pos=positions, width=weights) #width can be array of floats
您可以看到节点(14, 13)
包含最重的行和DataFrame df
中的最大值((13,13)
除外)。
答案 2 :(得分:4)
如果你在Linux中,并假设你的csv文件看起来像这样(例如):
23;89;3.49
23;14;1.29
75;14;2.85
14;75;2.9
75;23;0.9
23;27;4.9
您可以使用此程序:
import os
def build_G(csv_file):
#init graph dict
g={}
#here we open csv file
with open(csv_file,'r') as f:
cont=f.read()
#here we get field content
for line in cont.split('\n'):
if line != '':
fields=line.split(';')
#build origin node
if g.has_key(fields[0])==False:
g[fields[0]]={}
#build destination node
if g.has_key(fields[1])==False:
g[fields[1]]={}
#build edge origin>destination
if g[fields[0]].has_key(fields[1])==False:
g[fields[0]][fields[1]]=float(fields[2])
return g
def main():
#filename
csv_file="mynode.csv"
#build graph
G=build_G(csv_file)
#G is now a python dict
#G={'27': {}, '75': {'14': 2.85, '23': 0.9}, '89': {}, '14': {'75': 2.9}, '23': {'27': 4.9, '89': 3.49, '14': 1.29}}
#write to file
f = open('dotgraph.txt','w')
f.writelines('digraph G {\nnode [width=.3,height=.3,shape=octagon,style=filled,color=skyblue];\noverlap="false";\nrankdir="LR";\n')
f.writelines
for i in G:
for j in G[i]:
#get weight
weight = G[i][j]
s= ' '+ i
s += ' -> ' + j + ' [dir=none,label="' + str(G[i][j]) + '",penwidth='+str(weight)+',color=black]'
if s!=' '+ i:
s+=';\n'
f.writelines(s)
f.writelines('}')
f.close()
#generate graph image from graph text file
os.system("dot -Tjpg -omyImage.jpg dotgraph.txt")
main()
我之前正在寻找构建复杂图形的有效解决方案,这是我发现的最简单(没有任何python模块依赖)方法。
以下是无向图的图像结果(使用 dir = none ):
答案 3 :(得分:0)
您应该编辑csv文件开头的行,如下所示:
源目标类型权重 23 89无向34.9(即节点23和89之间有一个边缘,重34.9) 75 14无向28.5 等等......
之后,您可以将csv文件导入Gephi,以表示边缘厚度代表重量的图形,例如: enter image description here