networkx 基础用法
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()
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()
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))