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

NetworkX绘制基因有向图:节点形状、边属性异常修复求助

问题描述

我需要绘制一组基因的有向图,其中部分基因为癌基因(oncogene),部分为驱动基因(driver gene),基因间的交互通过特定形状、颜色及权重呈现。使用以下代码实现:

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

# 加权邻接矩阵
adjacency_matrix = np.array([
    [0, 0.2, 0, 0, 0.4],
    [0.0, 0, 0, 0, 0.1],
    [0.1, 0, 0, 0.1, 0],
    [0, 0, 0.3, 0, 0],
    [0.0, 0.0, 0, 0, 0]
])

# Katz中心性得分(已缩放至[1,10])
katz_centrality_scores = [0.95, 0.03, 0.65, 0.12, 0.06]
katz_centrality_scores = [9*(i-min(katz_centrality_scores))/(max(katz_centrality_scores) - min(katz_centrality_scores)) + 1 for i in katz_centrality_scores]

# 基因标签与类型(1=癌基因,2=驱动基因)
gene_labels = ["Gene1", "Gene2", "Gene3", "Gene4", "Gene5"]
gene_types = [1, 2, 1, 2, 2]

# 创建图并添加节点属性
G = nx.DiGraph()
for i in range(len(gene_labels)):
    node_color = 'red' if gene_types[i] == 1 else 'green'
    node_shape = 'v' if gene_types[i] == 1 else 's'
    node_size = katz_centrality_scores[i]*80
    G.add_node(gene_labels[i], color=node_color, shape=node_shape, size=node_size)

# 添加边属性
node_colors = [v['color'] for v in dict(G.nodes(data=True)).values()]
for i in range(len(gene_labels)):
    for j in range(len(gene_labels)):
        if adjacency_matrix[i][j] > 0:
            G.add_edge(gene_labels[i], gene_labels[j], weight=katz_centrality_scores[i], color=node_colors[i])

# 提取属性
node_colors = [G.nodes[n]['color'] for n in G.nodes()]
node_shapes = [G.nodes[n]['shape'] for n in G.nodes()]
node_sizes = [G.nodes[n]['size'] for n in G.nodes()]
edge_colors = [G[u][v]['color'] for u, v in G.edges()]
edge_weights = [G[u][v]['weight'] for u, v in G.edges()]

# 绘制图
pos = nx.spring_layout(G, seed=42)
curved_edges = [edge for edge in G.edges() if reversed(edge) in G.edges()]
straight_edges = [edge for edge in G.edges() if not reversed(edge) in G.edges()]

nx.draw(G, 
        pos, 
        node_color=node_colors, 
        node_size=node_sizes, 
        edge_color=edge_colors, 
        # node_shape=node_shapes,
        width=edge_weights, 
        with_labels=True, 
        edgelist=straight_edges, 
        arrowsize=25, 
        arrowstyle='->')

nx.draw(G, 
        pos, 
        node_color=node_colors, 
        node_size=node_sizes, 
        edge_color=edge_colors, 
        # node_shape=node_shapes,
        width=edge_weights, 
        with_labels=True, 
        edgelist=curved_edges, 
        connectionstyle='arc3, rad = 0.25',
        arrowsize=25,
        arrowstyle='->')

# 图例
red_patch = plt.Line2D([0], [0], marker='v', color='red', label='Oncogene', markersize=10, linestyle='None')
green_patch = plt.Line2D([0], [0], marker='s', color='green', label='Driver Gene', markersize=10, linestyle='None')
plt.legend(handles=[red_patch, green_patch], loc='upper right')

plt.title('Gene Network')
plt.axis('off')
plt.show()

运行后边属性如下:

list(G.edges(data=True))
# 输出:
[('Gene1', 'Gene2', {'weight': 10.0, 'color': 'red'}),
 ('Gene1', 'Gene5', {'weight': 10.0, 'color': 'red'}),
 ('Gene2', 'Gene5', {'weight': 1.0, 'color': 'green'}),
 ('Gene3', 'Gene1', {'weight': 7.065217391304349, 'color': 'red'}),
 ('Gene3', 'Gene4', {'weight': 7.065217391304349, 'color': 'red'}),
 ('Gene4', 'Gene3', {'weight': 1.8804347826086958, 'color': 'green'})]

但生成的图不符合预期:

  • 节点对(Gene3, Gene4)和(Gene4, Gene3)的边属性应为(红色,7.06)和(绿色,1.88),但实际图中(Gene4, Gene3)的边显示为红色,且粗细与前者一致;
  • 取消nx.draw中node_shape参数的注释后,出现错误:ValueError: Unrecognized marker style ['v', 's', 'v', 's', 's'],无法按基因类别设置节点形状(癌基因用三角形,驱动基因用正方形)。

解决方案

1. 修正双向边的颜色与粗细问题

问题根源:两次nx.draw分别处理直边和曲边时,直接使用全局的edge_colors和edge_weights会导致属性与边不匹配——因为curved_edges的顺序和全局边列表的顺序不一致。需要为直边和曲边分别提取对应的颜色与权重。

2. 修正节点形状设置问题

问题根源:nx.draw的node_shape参数仅支持单个标记样式,无法传入列表。需要按节点形状分组,分别绘制不同形状的节点。

完整修正后的代码

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

# 加权邻接矩阵
adjacency_matrix = np.array([
    [0, 0.2, 0, 0, 0.4],
    [0.0, 0, 0, 0, 0.1],
    [0.1, 0, 0, 0.1, 0],
    [0, 0, 0.3, 0, 0],
    [0.0, 0.0, 0, 0, 0]
])

# Katz中心性得分(已缩放至[1,10])
katz_centrality_scores = [0.95, 0.03, 0.65, 0.12, 0.06]
katz_centrality_scores = [9*(i-min(katz_centrality_scores))/(max(katz_centrality_scores) - min(katz_centrality_scores)) + 1 for i in katz_centrality_scores]

# 基因标签与类型(1=癌基因,2=驱动基因)
gene_labels = ["Gene1", "Gene2", "Gene3", "Gene4", "Gene5"]
gene_types = [1, 2, 1, 2, 2]

# 创建图并添加节点属性
G = nx.DiGraph()
for i in range(len(gene_labels)):
    node_color = 'red' if gene_types[i] == 1 else 'green'
    node_shape = 'v' if gene_types[i] == 1 else 's'
    node_size = katz_centrality_scores[i]*80
    G.add_node(gene_labels[i], color=node_color, shape=node_shape, size=node_size)

# 添加边属性
for i in range(len(gene_labels)):
    for j in range(len(gene_labels)):
        if adjacency_matrix[i][j] > 0:
            source_node = gene_labels[i]
            G.add_edge(source_node, gene_labels[j], weight=katz_centrality_scores[i], color=G.nodes[source_node]['color'])

# 绘制图
pos = nx.spring_layout(G, seed=42)
curved_edges = [edge for edge in G.edges() if reversed(edge) in G.edges()]
straight_edges = [edge for edge in G.edges() if not reversed(edge) in G.edges()]

# 提取直边和曲边的属性
straight_edge_colors = [G[u][v]['color'] for u, v in straight_edges]
straight_edge_weights = [G[u][v]['weight'] for u, v in straight_edges]
curved_edge_colors = [G[u][v]['color'] for u, v in curved_edges]
curved_edge_weights = [G[u][v]['weight'] for u, v in curved_edges]

# 绘制边
nx.draw_networkx_edges(G, pos, edgelist=straight_edges, edge_color=straight_edge_colors, width=straight_edge_weights, arrowsize=25, arrowstyle='->')
nx.draw_networkx_edges(G, pos, edgelist=curved_edges, edge_color=curved_edge_colors, width=curved_edge_weights, connectionstyle='arc3, rad=0.25', arrowsize=25, arrowstyle='->')

# 按形状分组绘制节点
oncogenes = [n for n in G.nodes() if G.nodes[n]['shape'] == 'v']
driver_genes = [n for n in G.nodes() if G.nodes[n]['shape'] == 's']
nx.draw_networkx_nodes(G, pos, nodelist=oncogenes, node_color='red', node_shape='v', node_size=[G.nodes[n]['size'] for n in oncogenes])
nx.draw_networkx_nodes(G, pos, nodelist=driver_genes, node_color='green', node_shape='s', node_size=[G.nodes[n]['size'] for n in driver_genes])

# 绘制标签
nx.draw_networkx_labels(G, pos, font_size=10)

# 图例
red_patch = plt.Line2D([0], [0], marker='v', color='red', label='Oncogene', markersize=10, linestyle='None')
green_patch = plt.Line2D([0], [0], marker='s', color='green', label='Driver Gene', markersize=10, linestyle='None')
plt.legend(handles=[red_patch, green_patch], loc='upper right')

plt.title('Gene Network')
plt.axis('off')
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:14:57