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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 01:53:12