如何通过CSV两列字符串匹配构建Networkx分类支序图?
解决NetworkX分类支序图的节点连接问题
问题背景
我正在大学项目中使用NetworkX制作分类支序图,需要将分类名称(taxon_name)与其父级名称(parent_name)连接,从物种名向上关联至科名直至支序图根部。需要比对CSV文件中这两列的名称并生成节点间的边,但当前代码无法实现预期的列搜索匹配。
原尝试代码
import networkx as nx import pandas as pd import matplotlib.pyplot as plt #df = pd.read_csv("E:/Escritorio/tp mat 3/pbdb_data.csv") #direccion labo df = pd.read_csv("D:/unsam/mat 3/TP 1/pbdb_data.csv") #direccion pc df = df.drop(["orig_no","taxon_no","record_type","flags","difference","accepted_no","parent_no","immpar_no","immpar_name","container_no","reference_no","is_extant"], axis=1) print(df) G = nx.Graph() G.add_nodes_from(df["taxon_name"]) for i in df["parent_name"]: for j in df["taxon_name"]: if df[i] == df[j]: x =+ 1 print (x) nx.draw_networkx(G) plt.draw()
CSV数据示例
taxon_rank,taxon_name,accepted_rank,accepted_name,parent_name,n_occs unranked clade,Dinosauria,unranked clade,Dinosauria,Dinosauriformes,1952 unranked clade,Megalosauridae,unranked clade,Megalosauridae,Dinosauria,2 unranked clade,Ornithischia,unranked clade,Ornithischia,Dinosauria,236 unranked clade,Genasauria,unranked clade,Genasauria,Ornithischia,208 unranked clade,Cerapoda,unranked clade,Cerapoda,Genasauria,173
原代码问题分析
- 嵌套循环遍历取值的方式效率极低,且
df[i]用法错误:i是parent_name的具体分类名称,不是DataFrame的列名,会触发KeyError。 - 仅做匹配计数,未实际创建节点间的连接边。
- 无向图
nx.Graph不适合体现层级分类的父子关系,有向图更贴合需求。 - 未处理
parent_name不在taxon_name中的根节点(如示例中的Dinosauriformes),会导致这类节点缺失。
修正后的代码
import networkx as nx import pandas as pd import matplotlib.pyplot as plt # 读取并清理数据 df = pd.read_csv("D:/unsam/mat 3/TP 1/pbdb_data.csv") drop_cols = ["orig_no","taxon_no","record_type","flags","difference","accepted_no","parent_no","immpar_no","immpar_name","container_no","reference_no","is_extant"] df = df.drop(drop_cols, axis=1) # 创建有向图,适合层级分类结构 G = nx.DiGraph() # 添加所有节点:包含taxon_name和parent_name的所有值,避免根节点丢失 all_nodes = set(df["taxon_name"]) | set(df["parent_name"]) G.add_nodes_from(all_nodes) # 遍历每行数据,添加父节点到子节点的边 for _, row in df.iterrows(): G.add_edge(row["parent_name"], row["taxon_name"]) # 绘制支序图,使用层级布局更清晰 plt.figure(figsize=(12, 8)) # 使用graphviz的dot布局需提前安装Graphviz工具和pygraphviz库,若无则替换为nx.spring_layout try: pos = nx.nx_agraph.graphviz_layout(G, prog="dot") except ImportError: pos = nx.spring_layout(G, k=0.15) # 备选布局 nx.draw_networkx(G, pos, with_labels=True, node_size=2000, font_size=10, arrows=True) plt.title("分类支序图") plt.axis("off") plt.show()
代码说明
- 改用
nx.DiGraph有向图,清晰体现父级到子级的层级指向。 - 合并两类名称作为节点集合,确保所有父节点(包括不在当前分类列表中的根节点)都被添加。
- 通过
iterrows()遍历行数据直接创建边,逻辑简洁高效。 - 提供两种布局方案:优先使用Graphviz的
dot布局生成标准层级图,若环境不支持则改用弹簧布局作为备选。
内容的提问来源于stack exchange,提问作者Regtest
相关产品推荐
相关产品推荐

