networkx 基础用法

networkx homepage 

1.一些基础方法和属性

import networkx as nx
import matplotlib.pyplot as plt

G = nx.Graph()          # 创建空的无向图
# G = nx.DiGraph()      # 创建空的有向图
# G = G.to_undirected() # 有向图变无向图

# 增加节点
G.add_node(1)                # 每次增加一个节点
G.add_nodes_from([3,5,8,6])  # iterable container
# (node, node_attribute_dict) 给节点附上属性(weights, labels, direct...)
G.add_nodes_from([(3, {'color':'red'}),
                  (2, {'color':'green'})])
print(list(G.nodes))    # 获取图中的所有节点 
G.nodes[1]['label']='a' # 增加节点属性
print(G.nodes.data())   # 获得节点的属性 [(1, {'label': 'a'}), (3, {'color': 'red'}), (5, {}), (8, {}), (6, {}), (2, {'color': 'green'})]

# 增加edges
G.add_edge(1,3)
G.add_edges_from([(1,3),(2,8),(1,5),(2,6,{'weight':3.1415}),(1,2),(0,9)])
# G.add_weighted_edges_from([(1,3,0.2),])
print(G[1]) # 以字典的形式返回节点1的邻居
print(G.has_edge(1,3)) # 判断节点对之间有没有连边
print(list(G.edges)) # 获取所有边,以列表的形式返回 print(list(G.adj[1])) # 节点1的邻居节点 list(nx.neighbors(G, 1)) print(G.degree[1]) # 节点的度 3 G[1][2]['weight'] = 3.1 # 为边添加权重 print(G.edges[(1,2)]) # 获取边的权重 {'weight': 3.1} print(G.number_of_nodes()) # 统计节点的数量 8 print(G.number_of_edges()) # 统计边的数量 6 print(nx.shortest_path(G, 3, 8)) # 计算节点3和8的最短路径 [3, 1, 2, 8] print(nx.shortest_path_length(G, 3, 8)) # 计算节点3和8最短路径长度 3 sp = dict(nx.all_pairs_shortest_path(G))# 计算每个节点到邻居节点的最短路径print(nx.number_connected_components(G))# 统计图中独立链接块的数量 2 nx.draw(G, with_labels=True) plt.show()

 

2.从DataFrame中加载节点和边的信息到图中

G=nx.from_pandas_edgelist(df, source='source', target='target', edge_attr=None, create_using=None)

df 至少包含源节点和目的节点两列,可以包含edge的属性,每一行代表一条链接

source\target: 源节点的列名称 和 目的节点的列名称;

edge_attr: edge属性的列名称,可以是 str or int, iterable, True, or None

create_using: 创建的图的类型,nx.Graph() 、nx.DiGraph() 、nx.MultiGraph()、nx.MultiDiGraph() 后两种允许节点之间有两条边

画图函数

有的函数还可以单独画出节点,边,节点的label,边的label,可以点击链接查看

nx.draw_networkx(G, pos=None,with_labels=True,labels=None, ) 这个是nx.draw()的加强版,可以标出节点的label和一些其他的特征

pos:图的布局(节点位置算法)

nx.random_layout(G, center=None, dim=2, seed=None) 在[0,1)范围内随机生成节点的位置坐标

nx.spring_layout(G, k=None, pos=None, ) 等等

import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt

node_1 = [1,2,3,4,5]
node_2 = [3,1,2,5,1]
weight = [0.3, 2, 1.2, 3, 0.8]
cost = ['a', 'b', 'c' ,'d' ,'e']
df = pd.DataFrame({'node_1':node_1, 'node_2':node_2,
              'weight':weight, 'cost':cost})

G = nx.from_pandas_edgelist(df, 'node_1', 'node_2',
                            edge_attr=True, create_using=nx.Graph())
print(G[1][3]['weight'])   # 0.3
print(G[1][3]['cost'])      # 'a'
pos = nx.random_layout(G, seed=23)  # 图的布局;返回一个字典,key表示节点,value表示节点的位置
nx.draw(G, pos=pos, with_labels=True)  
# 在图上标出边的权重
labels = {e:G.edges[e]['weight'] for e in G.edges}
# labels= nx.get_edge_attributes(G, 'weight')  获取边的labels
nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=labels)  # 在图上标出labels, 这里的pos要和上面的pos保持一致,否则边的权重会乱
plt.show()

 

3.创建图的邻接矩阵

A = nx.adjacency_matrix(G, nodelist=None, weight='weight') 

nodelist:节点在行和列的位置;如果是None,则按G.nodes排序

L = nx.laplacian_matrix(G, nodelist=None, weight='weight') 

拉普拉斯矩阵(L=D-A) D是节点的度的对角矩阵,A是节点的邻接矩阵

print(A) 是按节点对的形式显示;print(A.todense())  按矩阵形式显示

import pandas as pd
import networkx as nx

node_1 = [1,2,3,4,5]
node_2 = [3,1,2,5,1]
weight = [0.3, 2, 1.2, 1, 0.8]

df = pd.DataFrame({'node_1':node_1, 'node_2':node_2, 'weight':weight})

G = nx.from_pandas_edgelist(df, 'node_1', 'node_2',
                            edge_attr=True, create_using=nx.Graph())
nodes = list(G.nodes)
print(nodes)   # [1, 3, 2, 4, 5]
adj_G = nx.to_numpy_matrix(G, nodelist=nodes)  # 根据获得的nodes的排序来创建邻接矩阵,而不是顺序排列
print(adj_G)


'''
[[0. 0.3 2. 0. 0.8]
[0.3 0. 1.2 0. 0. ]
[2. 1.2 0. 0. 0. ]
[0. 0. 0. 0. 1. ]
[0.8 0. 0. 1. 0. ]]
'''

 

4.从邻接矩阵创建图

G=nx.from_numpy_matrix(A, parallel_edges=False, create_using=None) 

与dictionary,list,numpy,pandas有关的操作 

import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
A = np.array([[0,0,3], [2,0,0], [0,1,0]])

# 从邻接矩阵A创建有向权重图,节点标号为[0,1,2]
G = nx.from_numpy_matrix(A,create_using=nx.DiGraph())

pos = nx.random_layout(G, seed=23)
nx.draw(G, pos=pos, with_labels=True)
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=labels)
plt.show()

5.从文件中读图和将图写入文件

G=nx.read_edgelist(path, comments='#', delimiter=None,create_using=None, 

                                   nodetype=None, data=True, edgetype=None, encoding='utf-8')  

path:文件名,如果是打开的文件,则要以‘rb‘的形式打开;Filenames ending in .gz or .bz2 will be uncompressed.

comments如果文件的开头不是节点对,则要在文件开头加上 '#' ,否则会出错,例如:#source,destination

delimiter:节点之间的分隔符,默认为空格;如果是其他字符作为分隔符,这里一定要设置,否则读不出来

node_type:将节点数据从字符串转化为 int, float 等数据类型   edgetype:将边的数据从字符串转化为 int, float 等数据类型 

data:边的权重等数据,是一个bool或者元组; 例如权重数据 data=(('weight', float),),第一个位置表示key-name,第二个位置表示data-type 

nx.write_edgelist(G, path, comments='#', delimiter=' ', data=True, encoding='utf-8')

把一个图按节点对的形式写入文件

data:True表示写入边的属性;False表示不写入边的属性

G=nx.read_weighted_edgelist(G, path, comments='#', delimiter=' ', encoding='utf-8') 

读带权重的文件

G=nx.parse_edgelist(lines, comments='#', delimiter=None, create_using=None, nodetype=None, data=True) 

从列表里读节点对数据,lines是包含节点对的列表 例如['1 2', '1 3', '2 3']

 

6.生成一个Barabási–Albert (BA network) 和一个Watts–Strogatz small-world graph

import networkx as nx
import matplotlib.pyplot as plt

G1 = nx.barabasi_albert_graph(50, 5)
# nx.write_edgelist(G1,'dataset/BAnetwork', data=False)

G2 = nx.watts_strogatz_graph(50, 2, 0.1)
# nx.write_edgelist(G2, 'dataset/WSnetwork', data=False)

nx.draw(G1, with_labels=True)
plt.show()

nx.draw(G2, with_labels=True)
plt.show()

 

7.网络分析

import networkx as nx
import matplotlib.pyplot as plt

G = nx.read_edgelist('dataset/twitter-edges.edges', create_using=nx.DiGraph())
N, K = G.order(), G.size()  # 获取节点的数量,边的数量
avg_deg = float(K)/N        # 计算average degree(这是有向网络) 平均度是每个节点的度的总和除以节点总数
print(N, K, avg_deg)

# 绘制幂律分布图
in_degrees = G.in_degree()   # 统计每个节点的in_degree
out_degress = G.out_degree()
inDegrees = {}
outDegree = {}
for i in in_degrees:
    inDegrees[i[0]] = i[1]
for i in out_degress:
    outDegree[i[0]] = i[1]
in_values = sorted(set(inDegrees.values()))
inDegrees_values = list(inDegrees.values())
in_hist = [inDegrees_values.count(x) for x in in_values]  # 统计每种度的数量
out_values = sorted(set(outDegree.values()))
outDegrees_values = list(outDegree.values())
out_hist = [outDegrees_values.count(x) for x in out_values]
plt.figure()
plt.grid(True)
plt.loglog(in_values, in_hist, 'ro-')   # 绘制双对数曲线;幂律分布图
plt.loglog(out_values, out_hist, 'bv-')
plt.legend(['In-degree', 'Out-degree'])
plt.xlabel('Degree')
plt.ylabel('Number of nodes')
plt.show()

# 分析聚类系数
G_ud = G.to_undirected()
print('clust of 0:', nx.clustering(G_ud, '0'))  # '0'节点的聚类系数
clust_coefficients = nx.clustering(G_ud)
avg_clust = sum(clust_coefficients.values())/len(clust_coefficients)
print('avg_clust:', avg_clust)  # 平均聚类系数
print('avg_clust:', nx.average_clustering(G_ud))

 

posted @ 2020-08-14 16:27  菠萝机  阅读(5488)  评论(0编辑  收藏  举报