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
相关产品推荐
相关产品推荐

