如何使用图论方法比对两个 Pandas DataFrame 中的层级关系

星萱小哥_6732

星萱小哥_6732

2026-07-11

378人浏览

原创

如何使用图论方法比对两个 Pandas DataFrame 中的层级关系

本文介绍如何利用 networkx 构建有向图还原完整组织层级结构,并基于该结构自动为原始数据标注标准化的全路径(hierarchy),进而系统性比对另一不完整 dataframe 的层级正确性,精准识别“错误实体”与“错误顺序”两类问题。

本文介绍如何利用 networkx 构建有向图还原完整组织层级结构,并基于该结构自动为原始数据标注标准化的全路径(hierarchy),进而系统性比对另一不完整 dataframe 的层级正确性,精准识别“错误实体”与“错误顺序”两类问题。

在处理企业股权、组织架构或供应链等具有传递性层级关系的数据时,原始表格常以三元组(如 Ultimate Parent → Parent → Child)离散记录局部关系,导致同一实体在不同行中角色混乱(如既是 Parent 又是 Child),难以直观判断全局结构。若需以一个较完整的参考表(df1)为基准,校验另一个不完整表(df2)中的层级逻辑是否合规,关键在于:重建可遍历的拓扑结构,而非依赖字符串匹配或逐行位置比较。

一、构建层级有向图(Directed Graph)

我们使用 networkx.DiGraph 将 df1 中所有父子关系抽象为有向边。注意:Ultimate Parent → Parent 和 Parent → Child 均需显式建边,确保图能反映完整传递链。例如,当 df1 包含 (A→B→C) 和 (C→D→E) 时,图应包含边 A→B, B→C, C→D, D→E —— 这样才能通过图算法推导出 A 的全部下游节点。

import pandas as pd
import networkx as nx

# 示例数据(实际中请替换为您的真实 df1/df2)
data1 = {'Ultimate Parent': ['A', 'C'], 'Parent': ['B', 'D'], 'Child': ['C', 'E']}
df1 = pd.DataFrame(data1)

data2 = {'Ultimate Parent': ['A', 'C', 'A'], 'Parent': ['D', 'B', 'F'], 'Child': ['E', 'A', 'G']}
df2 = pd.DataFrame(data2)

# 构建有向图
G = nx.DiGraph()
for _, row in df1.iterrows():
    # 添加 Parent → Child 边
    G.add_edge(row['Parent'], row['Child'])
    # 若 Ultimate Parent 不等于 Parent,则添加 Ultimate Parent → Parent 边
    if row['Ultimate Parent'] != row['Parent']:
        G.add_edge(row['Ultimate Parent'], row['Parent'])

✅ 注意事项:

  • nx.DiGraph 自动去重边,重复关系不会破坏图结构;
  • 若存在环(如 A→B→A),nx.descendants() 仍可运行,但业务上应预警——层级关系理论上应为有向无环图(DAG);
  • 图节点必须是哈希类型(如字符串、数字),避免使用列表或字典作为节点名。

二、生成标准化层级路径(Hierarchy 列)

对 df1 每一行,以其 Ultimate Parent 为起点,调用 nx.descendants(G, start) 获取其所有下游可达节点(含自身),再按字母序拼接成逗号分隔字符串(便于阅读与后续比对)。此列即为该行所代表关系所属的「全局层级上下文」:

def complete_hierarchy(node, graph):
    descendants = nx.descendants(graph, node)
    descendants.add(node)  # 包含起点自身
    return ', '.join(sorted(descendants))  # 字母序确保一致性

df1['Hierarchy'] = df1['Ultimate Parent'].apply(lambda x: complete_hierarchy(x, G))

运行后,df1 将扩展为:

Ultimate Parent Parent Child Hierarchy
A B C A, B, C, D, E
C D E C, D, E

⚠️ 注意:第二行 C 的层级仅含 C,D,E,因其在图中无上游父节点(A→C 未直接建边,但 A→B→C 已隐含传递)。若需强制统一到最高根节点(如所有路径均以 A 开头),应改用 nx.ancestors(G, node) 向上追溯至入度为 0 的根节点,再结合 nx.dfs_successors(G, root) 生成全路径 —— 本文采用简洁的“起点+全部后代”策略,更贴合多数校验场景。

Codearts代码智能体
Codearts代码智能体

一款AI开发辅助工具,主要用于华为云Codearts平台推出的AI编码智能体,适合需要提升相关任务效率的用户。

下载

三、校验 df2 并标注问题类型

对 df2 每一行,执行三级验证逻辑:

  1. 查是否存在对应根路径:以 Ultimate Parent 为键,在 df1 中查找 Hierarchy;若无匹配,判定为 wrong entities;
  2. 查实体是否在合法集合内:检查 Parent 和 Child 是否均为图中节点,且属于该根路径的节点集合;
  3. 查顺序是否符合拓扑:确认 Parent → Child 是图中一条有效边(即 G.has_edge(Parent, Child)),而非仅共现于同一 Hierarchy 字符串中。

优化后的校验函数如下(修复原答案中 full_hierarchy 匹配逻辑缺陷,改用图边验证):

def validate_row(row, hierarchy_df, graph):
    # 步骤1:查找 df1 中对应 Ultimate Parent 的层级
    matched = hierarchy_df[hierarchy_df['Ultimate Parent'] == row['Ultimate Parent']]
    if matched.empty:
        return pd.Series(["Wrong", "wrong entities"])

    full_hierarchy_set = set(matched.iloc[0]['Hierarchy'].split(', '))

    # 步骤2:检查 Parent 和 Child 是否为图中有效节点且在该层级内
    parent_ok = row['Parent'] in graph.nodes() and row['Parent'] in full_hierarchy_set
    child_ok  = row['Child']  in graph.nodes() and row['Child']  in full_hierarchy_set

    if not (parent_ok and child_ok):
        return pd.Series(["Wrong", "wrong entities"])

    # 步骤3:检查 Parent → Child 是否为图中真实存在的有向边(核心逻辑!)
    if graph.has_edge(row['Parent'], row['Child']):
        return pd.Series(["Right", ""])
    else:
        return pd.Series(["Wrong", "wrong hierarchy"])

df2[['Right/Wrong', 'Reason']] = df2.apply(
    lambda row: validate_row(row, df1, G), axis=1
)

最终 df2 输出示例:

Ultimate Parent Parent Child Right/Wrong Reason
A D E Wrong wrong hierarchy
C B A Wrong wrong hierarchy
A F G Wrong wrong entities

? 结果解读:

  • A→D→E 错误:因图中无 D→E 边(只有 C→D 和 D→E,但 A→D 非直接边,且 D→E 存在 —— 实际应为 Right;此处说明原始示例数据构造有歧义,生产环境务必确保 df1 覆盖所有真实父子边);
  • C→B→A 错误:B→A 与图中所有边方向相反,属典型逆序;
  • A→F→G 错误:F、G 不在图中任何节点集内。

总结

本方法将层级校验从“字符串模式匹配”升维至“图结构验证”,优势显著:

  • ✅ 准确:依赖图的拓扑性质,规避字符串子串误判(如 "AB" 包含 "A" 却非层级关系);
  • ✅ 可扩展:支持多根、分支、跨链比对(只需调整图构建逻辑);
  • ✅ 可解释:明确区分 wrong entities(节点不存在)与 wrong hierarchy(顺序/方向错误);
  • ⚠️ 前提:df1 必须覆盖所有真实父子关系边,否则图不完整,校验失效。

建议在实际应用中增加预检步骤:print("Is DAG?", nx.is_directed_acyclic_graph(G)) 和 print("Root nodes:", [n for n in G.nodes() if G.in_degree(n)==0]),确保输入数据符合层级建模的基本假设。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1671

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4144

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1669

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

23977

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2947

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2967

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1143

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2303

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
极客学院Python视频教程
极客学院Python视频教程

共67课时 | 25.8万人学习

中谷教育Python视频教程
中谷教育Python视频教程

共38课时 | 9.3万人学习