python之知识图谱(networkx)
NetworkX 库介绍与使用指南
NetworkX 是 Python 中用于创建、操作和分析复杂网络(图结构) 的核心库,支持无向图、有向图、加权图、多重图等多种图类型,内置丰富的图算法(路径分析、连通性、中心性、社区检测等),广泛应用于社交网络分析、网络拓扑研究、路径规划等场景。
一、安装
使用 pip 安装最新版本:
pip install networkx # 基础安装 pip install networkx[all]# 包含所有依赖(如可视化、算法扩展)验证安装:我使用的版本是 3.6.1
import networkx as nx print(nx.__version__)# 输出版本号,如 3.2.1二、核心概念
| 概念 | 说明 |
|---|---|
| 节点(Node) | 图的基本单元,可绑定任意可哈希对象(整数、字符串、元组、自定义对象等) |
| 边(Edge) | 连接节点的关系,可绑定属性(如权重、标签、时间戳) |
| 图类型 | - Graph:无向图(默认),无自环/多重边- DiGraph:有向图- MultiGraph:无向多重图(允许多条边连同一对节点)- MultiDiGraph:有向多重图 |
三、基础操作:创建与编辑图
1. 创建图
初始化不同类型的图:
# 1. 无向图(默认) G = nx.Graph()# 2. 有向图 DG = nx.DiGraph()# 3. 无向多重图(允许多条边连接同一节点对) MG = nx.MultiGraph()# 4. 有向多重图 MDG = nx.MultiDiGraph()2. 添加节点
- 单个节点:
add_node() - 多个节点:
add_nodes_from() - 带属性的节点(如节点名称、权重):
# 添加单个节点 G.add_node(1)# 节点为整数 G.add_node("A", weight=0.8, label="核心节点")# 节点为字符串,带属性# 添加多个节点(可迭代对象) G.add_nodes_from([2,3,4])# 批量添加带属性的节点 G.add_nodes_from([(5,{"weight":0.5,"label":"普通节点"}),(6,{"weight":0.3})])# 从另一个图导入节点 G2 = nx.Graph() G2.add_nodes_from(G.nodes)# 复制G的所有节点3. 添加边
- 单个边:
add_edge() - 多个边:
add_edges_from() - 带权重/属性的边:
# 添加单个边(连接节点1和2) G.add_edge(1,2)# 带权重的边 G.add_edge(2,3, weight=5.0, label="强连接")# 添加多个边(列表形式,每个元素为(节点u, 节点v)或(节点u, 节点v, 属性字典)) G.add_edges_from([(3,4),(4,5,{"weight":2.0}),(5,6,{"weight":1.0,"label":"弱连接"})])# 多重图添加多条边(同一节点对) MG.add_edge(1,2, key=0, weight=1.0)# key区分同节点对的不同边 MG.add_edge(1,2, key=1, weight=2.0)4. 删除节点/边
# 删除单个节点 G.remove_node(6)# 删除多个节点 G.remove_nodes_from([4,5])# 删除单个边 G.remove_edge(1,2)# 删除多个边 G.remove_edges_from([(2,3),(3,4)])# 清空所有节点/边 G.clear()5. 查询图信息
# 1. 节点相关print("所有节点:",list(G.nodes))# 输出节点列表print("节点数量:", G.number_of_nodes())# 输出节点数print("节点1的属性:", G.nodes[1])# 获取节点1的属性(需先添加属性)# 2. 边相关print("所有边:",list(G.edges))# 输出边列表print("边数量:", G.number_of_edges())# 输出边数print("边(2,3)的属性:", G.edges[2,3])# 获取边(2,3)的属性# 3. 邻接节点(与指定节点相连的节点)print("节点2的邻接节点:",list(G.neighbors(2)))# 4. 图的基本信息 n_nodes = G.number_of_nodes() n_edges = G.number_of_edges() avg_degree =2* n_edges / n_nodes # 无向图平均度计算方式print(f"图的摘要:节点数={n_nodes}, 边数={n_edges}, 平均度={avg_degree:.2f}")四、图分析:常用算法与指标
NetworkX 内置大量图分析算法,以下是高频使用场景:
1. 度(Degree)分析
度表示节点的边数,有向图区分入度(in_degree) 和出度(out_degree):
# 无向图:节点的度print("节点2的度:", G.degree[2])# 带权重的度(求和所有边的权重)print("节点2的加权度:", G.degree(2, weight="weight"))# 有向图:入度/出度 DG.add_edges_from([(1,2),(2,3),(3,2)])print("节点2的入度:", DG.in_degree[2])# 2(1→2、3→2)print("节点2的出度:", DG.out_degree[2])# 1(2→3)2. 路径分析
- 最短路径(无权重/加权):
# 重置图(确保可运行) G = nx.Graph() G.add_edges_from([(1,2,{"weight":1}),(2,3,{"weight":5}),(1,3,{"weight":10}),(3,4,{"weight":2})])# 1. 无权重最短路径(节点数最少) shortest_path = nx.shortest_path(G, source=1, target=4)print("无权重最短路径:", shortest_path)# [1,2,3,4]# 2. 加权最短路径(Dijkstra算法) weighted_shortest_path = nx.shortest_path(G, source=1, target=4, weight="weight")print("加权最短路径:", weighted_shortest_path)# [1,2,3,4]# 加权最短路径长度 path_length = nx.shortest_path_length(G, source=1, target=4, weight="weight")print("加权路径长度:", path_length)# 1+5+2=83. 连通性分析
- 无向图:连通分量(子图内任意节点可达)
- 有向图:强连通分量(双向可达)/弱连通分量(忽略方向后可达)
# 无向图连通分量 G3 = nx.Graph() G3.add_edges_from([(1,2),(3,4),(4,5)]) components =list(nx.connected_components(G3))print("连通分量:", components)# [{1,2}, {3,4,5}]# 有向图强连通分量 DG3 = nx.DiGraph() DG3.add_edges_from([(1,2),(2,1),(2,3),(3,4)]) strong_components =list(nx.strongly_connected_components(DG3))print("强连通分量:", strong_components)# [{1,2}, {3}, {4}]4. 节点中心性(衡量节点重要性)
| 中心性类型 | 说明 | 函数 |
|---|---|---|
| 度中心性 | 节点度占总节点数的比例 | nx.degree_centrality() |
| 介数中心性 | 节点出现在最短路径的比例 | nx.betweenness_centrality() |
| 接近中心性 | 节点到其他节点的平均距离 | nx.closeness_centrality() |
示例:
# 计算度中心性 degree_centrality = nx.degree_centrality(G)print("度中心性:", degree_centrality)# {1:0.333, 2:0.666, 3:0.666, 4:0.333}# 计算介数中心性(加权) betweenness = nx.betweenness_centrality(G, weight="weight")print("介数中心性:", betweenness)五、图的可视化
NetworkX 结合 Matplotlib 实现可视化,支持自定义节点/边样式:
基础可视化
import matplotlib.pyplot as plt # 重置示例图 G = nx.Graph() G.add_edges_from([(1,2,{"weight":1}),(2,3,{"weight":5}),(1,3,{"weight":10}),(3,4,{"weight":2})])# 1. 基础布局(spring_layout:力导向布局,模拟物理引力) pos = nx.spring_layout(G)# 计算节点位置# 2. 绘制节点(自定义大小、颜色) nx.draw_networkx_nodes(G, pos, node_size=800, node_color="lightblue")# 3. 绘制边(自定义宽度:根据权重缩放) edge_weights =[G[u][v]["weight"]for u, v in G.edges] nx.draw_networkx_edges(G, pos, width=[w*0.5for w in edge_weights], edge_color="gray")# 4. 绘制节点标签、边权重 nx.draw_networkx_labels(G, pos, font_size=12) nx.draw_networkx_edge_labels(G, pos, edge_labels={(u,v):G[u][v]["weight"]for u,v in G.edges})# 5. 隐藏坐标轴 plt.axis("off") plt.title("加权无向图可视化") plt.show()常用布局
| 布局函数 | 适用场景 |
|---|---|
spring_layout() | 通用力导向布局(最常用) |
circular_layout() | 节点环形排列 |
random_layout() | 节点随机排列 |
kamada_kawai_layout() | 优化节点间距离,更美观 |
shell_layout() | 节点分层排列(如社交网络层级) |
六、综合示例:社交网络分析
# 1. 创建社交网络(无向图) social_graph = nx.Graph()# 2. 添加节点(用户),带属性(年龄、性别) social_graph.add_nodes_from([("Alice",{"age":25,"gender":"F"}),("Bob",{"age":30,"gender":"M"}),("Charlie",{"age":28,"gender":"M"}),("Diana",{"age":26,"gender":"F"}),("Eve",{"age":27,"gender":"F"})])# 3. 添加边(好友关系),带权重(亲密度1-10) social_graph.add_edges_from([("Alice","Bob",{"intimacy":9}),("Alice","Charlie",{"intimacy":6}),("Bob","Diana",{"intimacy":8}),("Charlie","Diana",{"intimacy":5}),("Diana","Eve",{"intimacy":7}),("Alice","Eve",{"intimacy":4})])# 4. 分析:# (1) 每个用户的好友数(度)print("=== 好友数 ===")for user in social_graph.nodes:print(f"{user}: {social_graph.degree[user]} 个好友")# (2) 亲密度加权的度中心性print("\n=== 亲密度中心性 ===") intimacy_centrality = nx.degree_centrality(social_graph, weight="intimacy")for user, score in intimacy_centrality.items():print(f"{user}: {score:.2f}")# (3) Alice到Eve的最短路径(按亲密度加权)print("\n=== Alice到Eve的最短路径 ===") path = nx.shortest_path(social_graph, source="Alice", target="Eve", weight="intimacy") path_length = nx.shortest_path_length(social_graph, source="Alice", target="Eve", weight="intimacy")print(f"路径:{' → '.join(path)},总亲密度:{path_length}")# (4) 可视化 pos = nx.kamada_kawai_layout(social_graph) nx.draw_networkx_nodes(social_graph, pos, node_size=1000, node_color=["pink"if social_graph.nodes[n]["gender"]=="F"else"lightblue"for n in social_graph.nodes]) nx.draw_networkx_edges(social_graph, pos, width=[e["intimacy"]*0.3for u,v,e in social_graph.edges(data=True)]) nx.draw_networkx_labels(social_graph, pos, font_size=12) nx.draw_networkx_edge_labels(social_graph, pos, edge_labels={(u,v):e["intimacy"]for u,v,e in social_graph.edges(data=True)}) plt.axis("off") plt.title("社交网络亲密度分析") plt.show()七、进阶扩展
- 与其他库结合:
- 高性能计算:结合
igraph/graph-tool(处理大规模图); - 可视化增强:结合
Pyvis(交互式可视化)、Plotly(动态图)。
- 高性能计算:结合
社区检测:使用 nx.community 模块(如 Louvain 算法):
from networkx.algorithms import community communities = community.louvain_communities(G, weight="weight")读取/保存图:支持 GraphML、GEXF、Pajek 等格式:
# 保存为GraphML nx.write_graphml(G,"my_graph.graphml")# 读取GraphML G_loaded = nx.read_graphml("my_graph.graphml")总结
NetworkX 是 Python 图分析的入门与核心工具,优势在于易用性强、API 直观、内置算法丰富,适合中小规模图(百万节点以内)的分析;若需处理超大规模图,可结合 Dask 分布式计算或专用图数据库(如 Neo4j)。