这篇教程将从基础到进阶,涵盖 networkx 的核心用法。
目录
- 安装与导入
- 图的创建
- 无向图
- 有向图
- 多重图
- 创建图的几种方式
- 添加节点和边
- 添加单个节点/边
- 添加多个节点/边
- 利用边属性
- 查询图信息
- 节点和边
- 节点数和边数
- 节点和边的度
- 图的遍历
- 深度优先遍历
- 广度优先遍历
- 算法应用
- 最短路径
- 中心性
- 可视化
- 使用
matplotlib进行简单绘制 - 可视化进阶技巧
- 使用
- 实际应用案例:社交网络分析
- 总结与资源
安装与导入
你需要安装 networkx,如果还没有安装,请在终端或命令行中运行:
pip install networkx
安装完成后,在你的 Python 脚本或交互式环境中导入它:
import networkx as nx import matplotlib.pyplot as plt # 通常用于可视化
图的创建
networkx 支持多种类型的图,最常见的三种是:
Graph: 无多重边(无平行边)的无向图。DiGraph: 无多重边的有向图。MultiGraph: 允许多重边的无向图。MultiDiGraph: 允许多重边的有向图。
示例:创建一个无向图
# 创建一个空的、无向的图
G = nx.Graph()
# 创建一个包含节点的图
G_with_nodes = nx.Graph()
G_with_nodes.add_nodes_from([1, 2, 3, 4])
print(f"空图的节点: {list(G.nodes())}")
print(f"带初始节点的图: {list(G_with_nodes.nodes())}")
添加节点和边
这是构建图的核心操作。
添加单个节点/边
# 添加单个节点
G.add_node("A")
# 添加单个边
G.add_edge("A", "B")
# 添加一个不存在的节点时,会自动创建
G.add_edge("B", "C")
添加多个节点/边
使用列表或元组来批量添加。
# 添加多个节点
G.add_nodes_from(["D", "E", "F"])
# 添加多条边
G.add_edges_from([("A", "D"), ("B", "E"), ("C", "F")])
利用边属性
networkx 的一个强大功能是,边(和节点)可以附加属性,就像字典一样,这在表示带权重的图(如网络中的延迟、社交网络中的关系强度等)时非常有用。
# 添加带权重的边
G.add_edge("A", "E", weight=5.0)
G.add_edge("B", "C", weight=2.5, relationship="friend")
# 修改或添加边的属性
G["A"]["B"]["color"] = "blue"
print("边的属性:", G.edges(data=True))
# 输出: [('A', 'B', {'color': 'blue'}), ('A', 'E', {'weight': 5.0}), ...]
查询图信息
构建好图后,我们需要查询它的基本信息。
# 获取所有节点
print("所有节点:", list(G.nodes()))
# 获取所有边
print("所有边:", list(G.edges()))
# 获取节点数
print("节点数量:", G.number_of_nodes())
# 获取边数
print("边数量:", G.number_of_edges())
# 获取节点的度(与该节点相连的边的数量)
print("各节点的度:", dict(G.degree()))
# 获取带权重的度(边的权重之和)
print("各节点的加权度:", dict(G.degree(weight="weight")))
图的遍历
遍历图是许多算法的基础。
深度优先遍历
从起始节点开始,沿着一条路径走到底,然后回溯。
# 从节点 'A' 开始深度优先遍历
dfs_edges = list(nx.dfs_edges(G, source="A"))
print("深度优先遍历的边:", dfs_edges)
# 获取遍历的节点顺序
dfs_nodes = list(nx.dfs_preorder_nodes(G, source="A"))
print("深度优先遍历的节点顺序:", dfs_nodes)
广度优先遍历
从起始节点开始,先访问所有邻居,然后再访问邻居的邻居,像水波一样扩散。
# 从节点 'A' 开始广度优先遍历
bfs_edges = list(nx.bfs_edges(G, source="A"))
print("广度优先遍历的边:", bfs_edges)
# 获取遍历的节点顺序
bfs_nodes = list(nx.bfs_preorder_nodes(G, source="A"))
print("广度优先遍历的节点顺序:", bfs_nodes)
算法应用
networkx 内置了大量经典图论算法。
最短路径
# 创建一个带权重的图
G_weighted = nx.Graph()
G_weighted.add_edges_from([
("A", "B", {"weight": 4}),
("A", "C", {"weight": 2}),
("B", "C", {"weight": 1}),
("B", "D", {"weight": 5}),
("C", "D", {"weight": 8}),
("C", "E", {"weight": 10}),
("D", "E", {"weight": 2})
])
# 计算从 'A' 到 'E' 的最短路径(按边的权重和)
shortest_path = nx.shortest_path(G_weighted, source="A", target="E", weight="weight")
print("从 A 到 E 的最短路径:", shortest_path) # 输出: ['A', 'B', 'D', 'E']
# 计算最短路径的长度
shortest_path_length = nx.shortest_path_length(G_weighted, source="A", target="E", weight="weight")
print("最短路径的长度:", shortest_path_length) # 输出: 11
中心性
中心性用于衡量图中节点的重要性。
- 度中心性: 连接数最多的节点最重要。
- 接近中心性: 到所有其他节点平均距离最短的节点最重要。
- 介数中心性: 在最多节点对之间的最短路径上出现的节点最重要。
# 度中心性
degree_centrality = nx.degree_centrality(G_weighted)
print("度中心性:", degree_centrality)
# 接近中心性
closeness_centrality = nx.closeness_centrality(G_weighted)
print("接近中心性:", closeness_centrality)
# 介数中心性
betweenness_centrality = nx.betweenness_centrality(G_weighted)
print("介数中心性:", betweenness_centrality)
可视化
使用 matplotlib 可以轻松地将图可视化。
使用 matplotlib 进行简单绘制
# 创建一个随机图用于演示 G_random = nx.erdos_renyi_graph(20, 0.1) # 20个节点,连接概率为0.1 # 设置绘图布局 pos = nx.spring_layout(G_random) # 一种常用的力导向布局 # 绘制节点 nx.draw_networkx_nodes(G_random, pos, node_size=500) # 绘制边 nx.draw_networkx_edges(G_random, pos, alpha=0.5) # 绘制节点标签 nx.draw_networkx_labels(G_random, pos) # 显示图形"随机图可视化") plt.show()
可视化进阶技巧
你可以根据节点的度或边的属性来调整可视化效果。
# 创建一个带权重的图
G_vis = nx.Graph()
G_vis.add_edges_from([
("A", "B", {"weight": 8}),
("A", "C", {"weight": 2}),
("B", "C", {"weight": 1}),
("B", "D", {"weight": 5}),
("C", "D", {"weight": 3}),
])
# 使用不同的布局
pos = nx.circular_layout(G_vis)
# 获取节点的度,用于设置节点大小
node_sizes = [300 * G_vis.degree(node) for node in G_vis.nodes()]
# 获取边的权重,用于设置边的宽度
edge_widths = [G_vis[u][v]['weight'] for u, v in G_vis.edges()]
# 绘制图形
plt.figure(figsize=(8, 8))
nx.draw_networkx_nodes(G_vis, pos, node_size=node_sizes, node_color='skyblue')
nx.draw_networkx_edges(G_vis, pos, width=edge_widths, alpha=0.7, edge_color='gray')
nx.draw_networkx_labels(G_vis, pos, font_size=12, font_family='sans-serif')
# 添加边权重标签
edge_labels = nx.get_edge_attributes(G_vis, 'weight')
nx.draw_networkx_edge_labels(G_vis, pos, edge_labels=edge_labels)
"带权重和大小调整的图")
plt.axis('off') # 关闭坐标轴
plt.show()
实际应用案例:社交网络分析
假设我们有一个简单的社交网络,表示谁是谁的朋友。
# 创建一个社交网络图
social_network = nx.Graph()
# 添加人(节点)
people = ["Alice", "Bob", "Charlie", "David", "Eve"]
social_network.add_nodes_from(people)
# 添加朋友关系(边)
friendships = [("Alice", "Bob"), ("Alice", "Charlie"), ("Bob", "David"), ("Charlie", "David"), ("David", "Eve")]
social_network.add_edges_from(friendships)
# 分析:谁是社交中心?
degree_centrality = nx.degree_centrality(social_network)
print("社交中心性(谁的朋友最多):")
for person, centrality in sorted(degree_centrality.items(), key=lambda item: item[1], reverse=True):
print(f"{person}: {centrality:.2f}")
# 分析:谁连接了不同的朋友圈?
# 我们可以给边添加属性,"since" (认识年份)
nx.set_edge_attributes(social_network, {("Alice", "Bob"): 2025, ("Alice", "Charlie"): 2025, ("Bob", "David"): 2025, ("Charlie", "David"): 2025, ("David", "Eve"): 2025}, "since")
# 可视化社交网络
pos = nx.spring_layout(social_network, seed=42) # seed使布局每次都一样
nx.draw(social_network, pos, with_labels=True, node_color='lightgreen', node_size=1500, font_size=10)"简单社交网络")
plt.show()
总结与资源
networkx 是一个非常灵活和强大的库,是进行图论分析和网络科学研究的利器。
核心要点回顾:
- 创建图:
nx.Graph(),nx.DiGraph()。 - 添加元素:
add_node(s),add_edge(s),并可以为它们添加属性。 - 查询信息:
nodes(),edges(),degree(),number_of_nodes()。 - 遍历:
nx.dfs_edges(),nx.bfs_edges()。 - 算法:
nx.shortest_path(),nx.degree_centrality()等。 - 可视化: 结合
matplotlib进行绘制,可以自定义节点大小、颜色、边宽度和标签。
进一步学习的资源:
- 官方文档: NetworkX Documentation (这是最好的资源,包含所有函数、类和教程)
- NetworkX 示例: NetworkX Gallery (有大量可运行的代码示例)
- 相关库:
- igraph: 一个更快的图论库,有 Python、R、C接口。
- graph-tool: 一个基于 C++ 的、高性能的 Python 图库。
- pyvis: 一个专注于交互式 Web 可视化的库。
希望这份详细的教程能帮助你快速上手 networkx!
