You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python或R绘制固定层级的多部图

多层层级图绘制实现方案

问题背景

我有两个带层级关联的邻接矩阵:

  • 矩阵a:行是a类节点,列是b类节点,表示a类节点指向b类节点
  • 矩阵b:行是b类节点(与a的列对应),列是c类节点,表示b类节点指向c类节点

给出的Python列表形式邻接矩阵:

import numpy as np
import pandas as pd
import networkx as nx

a_net= [[1,1,0],[0,0,0]]
b_net = [[1,0],[1,1],[0,0]]

转换为DataFrame的代码:

data_a = pd.DataFrame(a_net)
data_a.index = ['a1','a2'] 
data_a.columns = ['b1','b2','b3'] 

data_b = pd.DataFrame(b_net)
data_b.index = data_a.columns
data_b.columns = ['c1','c2']

我自行编写了合并为单个邻接矩阵的代码:

# 合并为单个邻接矩阵
for i in range(1,len(data_a.columns)+1):
    data_b['b'+str(i)] = [0]*len(data_b)
    
data_a['c1'] = [0]*len(data_a)
data_a['c2'] = [0]*len(data_a)

adj = pd.concat([data_a,data_b])

adj['a1'] = [0]*len(adj)
adj['a2'] = [0]*len(adj)

c1c2 = pd.DataFrame([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]])
c1c2.index = ['c1','c2']
c1c2.columns = adj.columns

adj = pd.concat([adj,c1c2])
adj

需求:绘制多层图,要求a开头节点处于第一层,b开头节点处于第二层,c开头节点处于第三层,同时显示无连接的节点(如a2、b3)。可提供Python或R语言实现方法,也可通过以下代码导出表格到R:

data_a.to_csv("a_net.csv")
data_b.to_csv("b_net.csv")

Python实现方案

1. 构建多层有向图

无需手动合并邻接矩阵,直接通过NetworkX构建图结构,添加所有节点和有效边:

import numpy as np
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt

# 初始化有向图
G = nx.DiGraph()

# 添加所有节点,并标记层级
a_nodes = ['a1', 'a2']
b_nodes = ['b1', 'b2', 'b3']
c_nodes = ['c1', 'c2']
G.add_nodes_from(a_nodes, layer=0)
G.add_nodes_from(b_nodes, layer=1)
G.add_nodes_from(c_nodes, layer=2)

# 添加a->b的边
for a in data_a.index:
    for b in data_a.columns:
        if data_a.loc[a, b] == 1:
            G.add_edge(a, b)

# 添加b->c的边
for b in data_b.index:
    for c in data_b.columns:
        if data_b.loc[b, c] == 1:
            G.add_edge(b, c)

2. 设置分层节点位置

手动定义每个节点的坐标,确保同一层级节点在同一竖线上:

# 分层位置定义
pos = {
    # 第一层(a类)
    'a1': (0, 1),
    'a2': (0, 0),
    # 第二层(b类)
    'b1': (1, 2),
    'b2': (1, 1),
    'b3': (1, 0),
    # 第三层(c类)
    'c1': (2, 1),
    'c2': (2, 0)
}

3. 绘制分层图

plt.figure(figsize=(8, 4))

# 按层级设置节点颜色
node_colors = [
    '#1f77b4' if node.startswith('a') 
    else '#ff7f0e' if node.startswith('b') 
    else '#2ca02c' 
    for node in G.nodes()
]

# 绘制节点、边和标签
nx.draw_networkx_nodes(G, pos, node_size=1500, node_color=node_colors, edgecolors='black')
nx.draw_networkx_edges(G, pos, arrowstyle='->', arrowsize=20, edge_color='gray')
nx.draw_networkx_labels(G, pos, font_size=12, font_weight='bold')

# 隐藏坐标轴并展示
plt.axis('off')
plt.tight_layout()
plt.show()

R语言实现方案

1. 导入数据并构建图结构

library(igraph)

# 导入数据
data_a <- read.csv("a_net.csv", row.names = 1)
data_b <- read.csv("b_net.csv", row.names = 1)

# 整理a->b的边列表
edges_ab <- which(data_a == 1, arr.ind = TRUE)
edges_ab <- data.frame(from = rownames(data_a)[edges_ab[,1]], to = colnames(data_a)[edges_ab[,2]])

# 整理b->c的边列表
edges_bc <- which(data_b == 1, arr.ind = TRUE)
edges_bc <- data.frame(from = rownames(data_b)[edges_bc[,1]], to = colnames(data_b)[edges_bc[,2]])

# 合并所有边并创建有向图
all_edges <- rbind(edges_ab, edges_bc)
g <- graph_from_data_frame(all_edges, directed = TRUE)

# 添加所有节点(包括孤立节点)
all_nodes <- c(rownames(data_a), colnames(data_a), colnames(data_b))
g <- add_vertices(g, length(setdiff(all_nodes, V(g)$name)), attr = list(name = setdiff(all_nodes, V(g)$name)))

2. 设置分层布局

# 标记节点层级
V(g)$layer <- ifelse(grepl("^a", V(g)$name), 1, ifelse(grepl("^b", V(g)$name), 2, 3))

# 手动设置分层坐标
pos <- data.frame(
  x = V(g)$layer,
  y = ave(1:length(V(g)$name), V(g)$layer, FUN = function(x) seq(length(x), 1))
)
rownames(pos) <- V(g)$name

3. 绘制分层图

plot(g, 
     layout = as.matrix(pos),
     vertex.size = 30,
     vertex.color = ifelse(V(g)$layer == 1, "#1f77b4", ifelse(V(g)$layer == 2, "#ff7f0e", "#2ca02c")),
     vertex.label = V(g)$name,
     vertex.label.cex = 1.2,
     edge.arrow.size = 0.5,
     edge.color = "gray",
     frame = FALSE)

内容的提问来源于stack exchange,提问作者Himan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:25:27