本文目录导读:

我来详细介绍一下如何使用NetworkX进行网络分层可视化,以下是几个实用的案例:
基础分层布局 - 使用shell_layout
import networkx as nx
import matplotlib.pyplot as plt
# 创建一个有向图
G = nx.DiGraph()
# 添加节点和边
edges = [
('A', 'B'), ('A', 'C'), ('A', 'D'),
('B', 'E'), ('B', 'F'),
('C', 'G'), ('C', 'H'),
('E', 'I'), ('F', 'I'), ('G', 'I'), ('H', 'I'),
('D', 'J'), ('J', 'K')
]
G.add_edges_from(edges)
# 定义每层的节点
layers = [
['A'], # 第1层
['B', 'C', 'D'], # 第2层
['E', 'F', 'G', 'H', 'J'], # 第3层
['I', 'K'] # 第4层
]
# 使用shell_layout实现分层
pos = nx.shell_layout(G, nlist=layers)
# 绘制图形
plt.figure(figsize=(10, 8))
nx.draw(G, pos, with_labels=True,
node_color='lightblue',
node_size=2000,
font_size=12,
font_weight='bold',
arrows=True,
arrowsize=20)
"网络分层布局 - shell_layout")
plt.show()
自定义分层布局
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
def hierarchical_layout(G, layers):
"""
自定义分层布局函数
参数:
G: networkx图
layers: 列表的列表,每层包含的节点
"""
pos = {}
layer_dist = 2.0 # 层间距离
node_dist = 1.5 # 同层节点间距
for layer_idx, layer_nodes in enumerate(layers):
# 计算y坐标(从下到上)
y = layer_idx * layer_dist
# 计算x坐标
n_nodes = len(layer_nodes)
if n_nodes == 1:
x_positions = [0]
else:
x_positions = np.linspace(
-node_dist * (n_nodes - 1) / 2,
node_dist * (n_nodes - 1) / 2,
n_nodes
)
# 为每层的每个节点设置位置
for node_idx, node in enumerate(layer_nodes):
pos[node] = (x_positions[node_idx], y)
return pos
# 示例2:更复杂的网络
G2 = nx.DiGraph()
# 添加更多节点和边
edges2 = [
('王总', '张经理'), ('王总', '李经理'),
('张经理', '赵主管'), ('张经理', '钱主管'),
('李经理', '孙主管'), ('李经理', '周主管'),
('赵主管', '员工1'), ('赵主管', '员工2'),
('钱主管', '员工3'),
('孙主管', '员工4'), ('孙主管', '员工5'),
('周主管', '员工6')
]
G2.add_edges_from(edges2)
# 定义分层(组织结构)
layers2 = [
['王总'], # CEO层
['张经理', '李经理'], # 经理层
['赵主管', '钱主管', '孙主管', '周主管'], # 主管层
['员工1', '员工2', '员工3', '员工4', '员工5', '员工6'] # 员工层
]
# 使用自定义分层布局
pos2 = hierarchical_layout(G2, layers2)
# 绘制
plt.figure(figsize=(12, 8))
nx.draw(G2, pos2, with_labels=True,
node_color='lightgreen',
node_size=2500,
font_size=10,
font_weight='bold',
arrows=True,
arrowsize=20,
edge_color='gray')
"公司组织结构分层图")
plt.show()
带颜色的分层可视化
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
def colored_hierarchical_layout(G, layers, colors):
"""
带颜色的分层布局
"""
pos = {}
layer_dist = 3.0
for layer_idx, layer_nodes in enumerate(layers):
y = layer_idx * layer_dist
n_nodes = len(layer_nodes)
if n_nodes == 1:
x_positions = [0]
else:
x_positions = np.linspace(
-layer_dist * (n_nodes - 1) / 2,
layer_dist * (n_nodes - 1) / 2,
n_nodes
)
for node_idx, node in enumerate(layer_nodes):
pos[node] = (x_positions[node_idx], y)
return pos
# 更复杂的网络示例
G3 = nx.DiGraph()
# 分层数据
layers3 = [
['数据源'], # 第1层
['数据采集', '数据清洗'], # 第2层
['特征工程', '模型训练'], # 第3层
['部署'], # 第4层
['监控', '反馈'] # 第5层
]
# 添加边
edges3 = [
('数据源', '数据采集'), ('数据源', '数据清洗'),
('数据采集', '特征工程'),
('数据清洗', '特征工程'),
('特征工程', '模型训练'),
('模型训练', '部署'),
('部署', '监控'), ('部署', '反馈')
]
G3.add_edges_from(edges3)
# 为每层定义颜色
layer_colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
# 计算位置
pos3 = colored_hierarchical_layout(G3, layers3)
# 为每个节点分配颜色
node_colors = []
for node in G3.nodes():
for layer_idx, layer_nodes in enumerate(layers3):
if node in layer_nodes:
node_colors.append(layer_colors[layer_idx])
break
# 绘制
plt.figure(figsize=(14, 10))
nx.draw(G3, pos3, with_labels=True,
node_color=node_colors,
node_size=3000,
font_size=12,
font_weight='bold',
font_color='black',
arrows=True,
arrowsize=25,
edge_color='gray',
width=2,
alpha=0.9)
# 添加图例
for idx, (layer_name, color) in enumerate(zip(
['数据源层', '数据处理层', '模型构建层', '部署层', '监控层'],
layer_colors
)):
plt.scatter([], [], c=color, label=layer_name, s=200)
plt.legend(loc='upper left', bbox_to_anchor=(1, 1))"机器学习流水线分层架构", fontsize=16, pad=20)
plt.tight_layout()
plt.show()
交互式分层网络
import networkx as nx
import matplotlib.pyplot as plt
from matplotlib.patches import FancyBboxPatch
import numpy as np
def draw_fancy_hierarchical_network(G, layers):
"""
绘制精美的分层网络图
"""
fig, ax = plt.subplots(figsize=(15, 10))
# 计算位置
pos = {}
layer_dist = 3.0
node_dist = 2.0
for layer_idx, layer_nodes in enumerate(layers):
y = layer_idx * layer_dist
n_nodes = len(layer_nodes)
if n_nodes == 1:
x_positions = [0]
else:
x_positions = np.linspace(
-node_dist * (n_nodes - 1) / 2,
node_dist * (n_nodes - 1) / 2,
n_nodes
)
for node_idx, node in enumerate(layer_nodes):
pos[node] = (x_positions[node_idx], y)
# 绘制边
for edge in G.edges():
x1, y1 = pos[edge[0]]
x2, y2 = pos[edge[1]]
# 绘制曲线箭头
ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
arrowprops=dict(arrowstyle='->',
color='gray',
lw=2,
connectionstyle='arc3,rad=0.2'))
# 绘制节点
for node, (x, y) in pos.items():
# 找到节点所属的层
node_color = 'lightblue'
for layer_idx, layer_nodes in enumerate(layers):
if node in layer_nodes:
# 根据层级设置颜色
colors = plt.cm.Set3(np.linspace(0, 1, len(layers)))
node_color = colors[layer_idx]
break
# 绘制圆角矩形节点
rect = FancyBboxPatch((x-0.5, y-0.3), 1, 0.6,
boxstyle="round,pad=0.1",
facecolor=node_color,
edgecolor='black',
linewidth=2)
ax.add_patch(rect)
# 添加标签
ax.text(x, y, node, ha='center', va='center',
fontsize=12, fontweight='bold')
# 添加层标签
layer_labels = ['数据层', '处理层', '分析层', '展示层']
for layer_idx, label in enumerate(layer_labels):
y = layer_idx * layer_dist
ax.text(-node_dist * 2, y, label,
fontsize=14, fontweight='bold',
ha='center', va='center',
bbox=dict(boxstyle='round,pad=0.3',
facecolor='wheat',
edgecolor='gray'))
ax.set_xlim(-node_dist * 3, node_dist * 3)
ax.set_ylim(-layer_dist, layer_dist * len(layers))
ax.axis('off')
plt.title("精致分层网络可视化", fontsize=16)
return fig, ax
# 使用示例
G4 = nx.DiGraph()
layers4 = [
['传感器1', '传感器2', '传感器3'],
['数据处理器'],
['分析引擎'],
['仪表盘']
]
edges4 = [
('传感器1', '数据处理器'),
('传感器2', '数据处理器'),
('传感器3', '数据处理器'),
('数据处理器', '分析引擎'),
('分析引擎', '仪表盘')
]
G4.add_edges_from(edges4)
draw_fancy_hierarchical_network(G4, layers4)
plt.show()
动态分层网络(带动画)
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
def create_animated_hierarchy():
fig, ax = plt.subplots(figsize=(12, 8))
G = nx.DiGraph()
# 定义层和节点
layers = {
0: ['A'],
1: ['B', 'C'],
2: ['D', 'E', 'F'],
3: ['G', 'H']
}
edges = [
('A', 'B'), ('A', 'C'),
('B', 'D'), ('B', 'E'),
('C', 'F'), ('C', 'D'),
('D', 'G'), ('E', 'H'), ('F', 'H')
]
G.add_edges_from(edges)
# 计算初始位置
pos = {}
for layer, nodes in layers.items():
y = -layer
n_nodes = len(nodes)
if n_nodes == 1:
x_pos = [0]
else:
x_pos = np.linspace(-1.5, 1.5, n_nodes)
for i, node in enumerate(nodes):
pos[node] = (x_pos[i], y)
def update(frame):
ax.clear()
# 动态颜色变化
colors = plt.cm.rainbow(frame / 100)
nx.draw(G, pos, with_labels=True,
node_color=[colors] * G.number_of_nodes(),
node_size=2000,
font_size=12,
font_weight='bold',
arrows=True,
arrowsize=20,
ax=ax)
ax.set_title(f"动态分层网络 - 帧 {frame}", fontsize=14)
ax.set_xlim(-3, 3)
ax.set_ylim(-4, 1)
ani = animation.FuncAnimation(fig, update, frames=100,
interval=200, blit=False)
return ani
# 创建动画(需要取消注释来运行)
# ani = create_animated_hierarchy()
# plt.show()
使用建议
-
选择合适的布局:
shell_layout:适合简单的分层结构hierarchical_layout:适合自定义复杂分层spring_layout:适合显示节点间的关系强度
-
颜色使用:
- 每层使用不同颜色
- 同层节点使用相似色系
- 重要节点使用突出颜色
-
交互性:
- 可以使用
plotly或bokeh添加交互 - 添加鼠标悬停信息
- 实现拖动和缩放功能
- 可以使用
这些案例涵盖了从基础到高级的各种NetworkX分层布局方法,你可以根据具体需求选择合适的方式。