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

如何将DataFrame存储的subclassOf层级输出为带缩进的文本列表

子类层级缩进打印问题

问题描述

我有一组subclassOf层级关系可通过DataFrame表示,其中subjects是objects的子类。我需要将该层级打印为带缩进的列表,缩进代表当前术语是上一行术语的子类。我目前使用递归函数实现,已经可以正确增加缩进,但找不到合适的位置通过减少prefix_level来回退缩进,导致输出不符合预期。欢迎提供任意解决方案,无需基于我现有的实现调整。

示例数据

构造层级关系DataFrame的代码如下:

import pandas as pd
current_direct_sco = pd.DataFrame(
    {
        "subject": {
            986: "ENVO:01000025",
            989: "ENVO:01000028",
            990: "ENVO:01000029",
            991: "ENVO:01000030",
            1011: "ENVO:01000050",
            1014: "ENVO:01000053",
            1015: "ENVO:01000054",
            1096: "ENVO:01000127",
            1242: "ENVO:01000252",
            1243: "ENVO:01000253",
        },
        "object": {
            986: "ENVO:01000024",
            989: "ENVO:01000024",
            990: "ENVO:01000024",
            991: "ENVO:01000024",
            1011: "ENVO:01000029",
            1014: "ENVO:01000030",
            1015: "ENVO:01000030",
            1096: "ENVO:01000024",
            1242: "ENVO:00000873",
            1243: "ENVO:00000873",
        },
    }
)

数据内容如下:

序号subjectobject
986ENVO:01000025ENVO:01000024
989ENVO:01000028ENVO:01000024
990ENVO:01000029ENVO:01000024
991ENVO:01000030ENVO:01000024
1011ENVO:01000050ENVO:01000029
1014ENVO:01000053ENVO:01000030
1015ENVO:01000054ENVO:01000030
1096ENVO:01000127ENVO:01000024
1242ENVO:01000252ENVO:00000873
1243ENVO:01000253ENVO:00000873

可通过igraph绘制层级结构图(需安装pycairo依赖):

import igraph as ig
g = ig.Graph.TupleList(
    current_direct_sco.itertuples(index=False), directed=True, vertex_name_attr="label"
)
ig.plot(g)

根节点计算

首先计算层级的根节点(即只作为父类出现、没有上级类的术语):

roots = list(set(current_direct_sco["object"]) - set(current_direct_sco["subject"]))
print(roots)

输出结果:

['ENVO:00000873', 'ENVO:01000024']

现有实现及问题

当前递归实现代码如下:

def recurse_envo(starting_term):
    global prefix_level
    global prefix_chunk
    global current_prefix
    print(current_prefix + starting_term)
    current_children = list(
        current_direct_sco["subject"].loc[current_direct_sco["object"] == starting_term]
    )
    if len(current_children) > 0:
        prefix_level = prefix_level + 1
        current_prefix = prefix_chunk * prefix_level
        for current_child in current_children:
            recurse_envo(current_child)

for i in roots:
    first_term = i
    prefix_level = 0
    prefix_chunk = "  "
    current_prefix = ""
    recurse_envo(first_term)

当前错误输出

ENVO:00000873
  ENVO:01000252
  ENVO:01000253
ENVO:01000024
  ENVO:01000025
  ENVO:01000028
  ENVO:01000029
    ENVO:01000050
    ENVO:01000030
      ENVO:01000053
      ENVO:01000054
      ENVO:01000127

错误原因是ENVO:01000127实际并不是ENVO:01000030的子类,缩进层级错误。

期望输出

ENVO:00000873
  ENVO:01000252
  ENVO:01000253
ENVO:01000024
  ENVO:01000025
  ENVO:01000028
  ENVO:01000029
    ENVO:01000050
  ENVO:01000030
    ENVO:01000053
    ENVO:01000054
  ENVO:01000127

解决方案

问题核心是使用全局变量存储缩进层级,遍历完子节点后没有回退层级值,导致后续同级节点继承了子节点的缩进层级。改为将缩进层级作为递归函数的入参传递即可解决:

prefix_chunk = "  "

def recurse_envo(starting_term, level=0):
    # 打印当前节点
    print(prefix_chunk * level + starting_term)
    # 获取所有子节点
    current_children = current_direct_sco["subject"].loc[current_direct_sco["object"] == starting_term].tolist()
    # 递归遍历子节点,层级+1
    for child in current_children:
        recurse_envo(child, level + 1)

# 遍历所有根节点
for root in roots:
    recurse_envo(root)

运行上述代码即可得到符合预期的缩进输出。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:06:04