创建网络图

时间:2016-03-06 18:44:01

标签: graph social-networking

我以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等)。边缘的厚度应代表边缘重量。

4 个答案:

答案 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_dataframepandas进行交互。假设您的数据采用上述格式的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。但是,正如您所看到的那样,边缘宽度相同:
Unweighted

但是你拥有增加重量所需的一切。首先将权重放入名为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

Weighted

您可以看到节点(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 ):

enter image description here

答案 3 :(得分:0)

您应该编辑csv文件开头的行,如下所示:

源目标类型权重 23 89无向34.9(即节点23和89之间有一个边缘,重34.9) 75 14无向28.5 等等......

之后,您可以将csv文件导入Gephi,以表示边缘厚度代表重量的图形,例如: enter image description here