如何在Python中绘制带节点标签的树?ETE工具使用疑问
问题需求
需要用Python复现带所有节点标签的树状图(对应Furnival, G. M.与Wilson, R. W. 1974年《Regression by leaps and bounds》论文第75页图5的部分结构),且支持绘制同类树结构。使用ETE3工具时发现仅能标注叶子节点,无法为内部节点设置标签,需解决全节点标签的绘制问题。
方案一:基于ETE3实现全节点标签标注
ETE3支持为内部节点设置标签,只是不能直接在常规Newick字符串中同时定义结构与内部节点标签,可通过以下两种方式实现:
方式1:手动遍历设置节点标签
先构建树的结构框架,再逐个为所有节点(根、内部节点、叶子)指定标签,最后自定义显示样式:
from ete3 import Tree, TreeStyle, TextFace # 构建树的结构骨架(用空占位符) t = Tree("(, (, (, ()), (, , ()), (, (, ()), ), ));") # 按目标树的节点顺序准备所有标签(深度优先遍历顺序) all_labels = [ "12345", "", # 根节点下的主内部分支节点 "1234", "1235", "123", "1245", "124", "125", "12", "1345", "134", "135", "13", "145", "2345" ] # 遍历节点并赋值标签 for node, label in zip(t.traverse("preorder"), all_labels): node.name = label # 定义树的显示样式,确保所有节点标签可见 ts = TreeStyle() ts.show_leaf_name = False # 关闭默认叶子名称显示 ts.rotation = 90 # 旋转树方向匹配目标图(可选) # 自定义节点标签显示逻辑 def node_layout(node): if node.name: # 在分支右侧添加标签文本 node.add_face(TextFace(node.name, fsize=10), column=0, position="branch-right") ts.layout_fn = node_layout # 显示树 t.show(tree_style=ts)
方式2:解析带内部节点标签的Newick字符串
ETE3支持解析扩展Newick格式,用[&label=xxx]为内部节点指定标签:
from ete3 import Tree, TreeStyle # 扩展Newick字符串,内部节点用[&label=xxx]标注 t = Tree("(12345, (1234[&label=1234], (1235[&label=1235], 123), (1245[&label=1245], 124, 125, 12), (1345[&label=1345], (134[&label=134], (135[&label=135], 13)), 145), 2345));") # 设置显示样式,启用内部节点标签显示 ts = TreeStyle() ts.show_leaf_name = True ts.show_internal = True # 显示内部节点的label属性 ts.rotation = 90 t.show(tree_style=ts)
方案二:基于NetworkX + Matplotlib实现灵活绘图
如果需要更自由的布局和样式控制,可使用NetworkX构建树结构,结合Matplotlib绘图:
import networkx as nx import matplotlib.pyplot as plt # 定义树的边关系(父节点 → 子节点) tree_edges = [ ("root", "12345"), ("root", "inner_main"), ("inner_main", "1234"), ("inner_main", "inner_1235"), ("inner_1235", "1235"), ("1235", "123"), ("inner_main", "inner_1245"), ("inner_1245", "1245"), ("1245", "124"), ("1245", "125"), ("1245", "12"), ("inner_main", "inner_1345"), ("inner_1345", "1345"), ("1345", "134"), ("134", "135"), ("135", "13"), ("1345", "145"), ("inner_main", "2345") ] # 创建树结构的图 G = nx.Graph() G.add_edges_from(tree_edges) # 使用Graphviz的dot布局(需提前安装Graphviz),设置从左到右的方向 pos = nx.nx_agraph.graphviz_layout(G, prog="dot", args="-Grankdir=LR") # 绘制树 plt.figure(figsize=(14, 9)) nx.draw( G, pos, with_labels=True, node_size=2200, node_color="#ffffff", edge_color="#333333", font_size=11, font_weight="bold" ) plt.title("Regression by leaps and bounds Tree") plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者Michael Baudin
相关产品推荐
相关产品推荐

