共计 3605 个字符,预计需要花费 10 分钟才能阅读完成。
提醒:本文最后更新于 2023-10-07 17:33,文中所关联的信息可能已发生改变,请知悉!
在这篇文章中,我将介绍如何用 Python 和 NetworkX 库来绘制一个学生和教师之间的关系图,以及如何查询两个节点之间的关系路径。这个关系图可以很好的帮助我们了解学生和教师之间的联系,以及他们所参与的课程和活动。
准备工作
首先,我们需要安装 Python 和 NetworkX 库。Python 是一种广泛使用的编程语言,它有很多强大的功能和丰富的库。NetworkX 是一个用于创建、操作和分析复杂网络的 Python 库,它提供了很多方便的函数和算法。我们可以用 pip 命令来安装这两个库:
pip install python
pip install networkx
然后,我们需要导入 NetworkX 库和 matplotlib.pyplot 模块。matplotlib.pyplot 是一个用于绘制图形的模块,它可以与 NetworkX 配合使用,让我们可以可视化网络结构。我们可以用 import 语句来导入这两个模块:
import networkx as nx
import matplotlib.pyplot as plt
创建图
接下来,我们需要创建一个有向图对象,并向其中添加节点和边。有向图是一种网络结构,它由节点(也叫顶点)和边(也叫弧)组成,每条边都有一个方向,表示从一个节点指向另一个节点。我们可以用 nx.DiGraph()
函数来创建一个空的有向图对象,并赋值给变量 G:
G = nx.DiGraph()
然后,我们需要定义节点和边的数据。在这个例子中,我们假设有三个学生(张三、李四、王五),三个教师(周老师、梁老师、凌老师),以及他们所参与的课程和活动(AI 实训中心、鑫华楼 207、明华楼 345、智慧技术概论、数据结构、自然语言处理、周二、周三、周四)。我们可以用列表来存储这些数据,并赋值给变量 nodes
和edges
:
# 定义节点
nodes = [" 张三 ", " 李四 ", " 周老师 ", " 梁老师 ", "AI 实训中心 ", " 鑫华楼 207",
" 智慧技术概论 ", " 数据结构 ", " 周三 ", " 周二 ", " 王五 ", " 凌老师 ", " 周四 "]
# 定义边
edges = [(" 张三 ", " 周老师 "),
(" 李四 ", " 周老师 "),
(" 王五 ", " 凌老师 "),
(" 王五 ", " 周老师 "),
(" 张三 ", " 凌老师 "),
(" 李四 ", " 凌老师 "),
(" 周三 ", "AI 实训中心 "),
(" 周四 ", " 明华楼 345"),
("AI 实训中心 ", " 智慧技术概论 "),
(" 明华楼 345", " 自然语言处理 "),
(" 李四 ", " 梁老师 "),
(" 张三 ", " 梁老师 "),
(" 周二 ", " 鑫华楼 207"),
(" 鑫华楼 207", " 数据结构 "),
(" 周老师 ", " 周三 "),
(" 梁老师 ", " 周二 "),
(" 凌老师 ", " 周四 "),
]
# 定义节点位置
pos = {" 张三 ": (0, 1),
" 李四 ": (0, 0),
" 王五 ": (0, -1),
" 周老师 ": (2, 0),
" 梁老师 ": (2, 2),
" 凌老师 ": (2, -2),
"AI 实训中心 ": (4, 0),
" 鑫华楼 207": (4, 2),
" 明华楼 345": (4, -2),
" 智慧技术概论 ": (6, 0),
" 数据结构 ": (6, 2),
" 自然语言处理 ": (6, -2),
" 周四 ": (3, -2),
" 周三 ": (3, 0),
" 周二 ": (3, 2),
}
接着,我们需要将节点和边添加到图中。我们可以用 G.add_nodes_from()
函数来添加节点列表,用 G.add_edges_from()
函数来添加边列表:
# 将节点添加到图中
G.add_nodes_from(nodes)
# 将边添加到图中
G.add_edges_from(edges)
绘制图
最后,我们需要绘制图,并显示节点和边的标签。我们可以用 plt.figure()
函数来创建一个图形对象,并指定大小。然后,我们可以用 plt.rcParams[]
字典来设置字体,以便显示中文。再用 nx.draw_networkx_nodes()
函数来绘制节点,并指定颜色和大小。用 nx.draw_networkx_edges()
函数来绘制边,并指定颜色、宽度和透明度。最后用 nx.draw_networkx_labels()
函数来绘制节点标签,并添加偏移以避免重叠。当然,我们也可以用 plt.title()
函数来添加标题,用 plt.axis()
函数来关闭坐标轴。代码如下:
plt.figure(figsize=(12, 8))
plt.rcParams['font.sans-serif'] = ['simHei']
# 绘制节点,指定颜色和大小
nx.draw_networkx_nodes(G, pos, node_color='lightblue', node_size=500)
# 绘制边
nx.draw_networkx_edges(G, pos, edge_color='gray', width=1.0, alpha=0.7)
# 绘制节点标签,并添加偏移以避免重叠
node_labels = {node: node for node in G.nodes()}
node_label_pos = {k: (v[0], v[1] + 0.1)
for k, v in pos.items()} # 在 y 轴上添加 0.1 的偏移
nx.draw_networkx_labels(G, node_label_pos, labels=node_labels, font_size=12)
# 自定义图的外观
plt.title('学生和教师关系图')
plt.axis('off')
查询关系
除了绘制图之外,我们还可以用 NetworkX
库提供的一些函数和算法来查询两个节点之间的关系路径。例如,我们可以用 nx.all_simple_paths()
函数来找出从一个节点到另一个节点的所有简单路径(不重复经过任何节点的路径)。我们可以将这个函数封装在一个自定义的函数中,命名为 find_relationship()
,并接受两个参数:node1
和node2
,分别表示起点和终点。在这个函数中,我们首先用 list()
函数将 nx.all_simple_paths()
函数的返回值转换为一个列表,并赋值给变量 paths
。然后,我们判断paths
是否为空,如果不为空,则表示存在关系路径,我们就打印出每条路径,并在图上显示查询结果;如果为空,则表示不存在关系路径,我们就打印出提示信息,并在图上显示查询结果。代码如下:
# 查找两个节点之间的关系
def find_relationship(node1, node2):
paths = list(nx.all_simple_paths(G, source=node1, target=node2))
if paths:
print(f" 从 {node1} 到 {node2} 的关系路径:")
for path in paths:
print(" -> ".join(path))
# 在图上显示查询结果
result_text = f" 从 {node1} 到 {node2} 的关系路径:\n"
result_text += "\n".join([" -> ".join(path) for path in paths])
plt.annotate(result_text, xy=(0, 0), xycoords='axes fraction', fontsize=12,
bbox=dict(boxstyle="round,pad=0.5", edgecolor="blue", facecolor="lightyellow"))
else:
result_text = f"{node1} 和 {node2} 之间不存在关系。"
plt.annotate(result_text, xy=(0, 0), xycoords='axes fraction', fontsize=12,
bbox=dict(boxstyle="round,pad=0.5", edgecolor="blue", facecolor="lightyellow"))
print(result_text)
示例查询
为了演示这个函数的效果,我们可以用一个示例查询来调用它。例如,我们可以查询王五和自然语言处理之间的关系路径:
# 示例查询
find_relationship(" 王五 ", " 自然语言处理 ")
运行这段代码后,我们可以看到输出结果如下:
从 王五到 自然语言处理 的关系路径:
王五 -> 凌老师 -> 周四 -> 明华楼 345 -> 自然语言处理
我们还可以使用 plt.show()
看到图上显示了查询结果:
plt.show()
如下图所示:
总结
通过这篇文章,我们学习了如何用 Python
和NetworkX
库来绘制一个学生和教师之间的关系图,以及如何查询两个节点之间的关系路径。这个关系图可以帮助我们了解学生和教师之间的联系,以及他们所参与的课程和活动。我们还可以用 NetworkX
库提供的一些函数和算法来分析网络结构的特征,例如度数、聚类系数、最短路径、连通性等。如果你对这些内容感兴趣,可以参考 NetworkX 官方文档 和NetworkX 教程 来进一步学习。