如何比较 2 个数据帧中的层次结构 [Pandas]?

问题描述 投票:0回答:1

我有 2 个数据框捕获同一数据集的层次结构。 Df1相比Df2更加完整,所以我想以Df1为标准来分析Df2中的层次结构是否正确。然而,这两个数据帧都以不好的方式显示层次结构,因此很难逐行了解完整的结构。

例如。 A公司可能拥有子公司:B、C、D、E,关系是A拥有B拥有C拥有D拥有E。 在Df1中,会显示:

| Ultimate Parent | Parent | Child |
| --------------- | ------ |-------|
| A               | B      | C     |
| C               | D      | E     |

所以如果分解逐行分析,同一个实体可以同时显示为“最终父级”或“子级”,这就变得复杂了。

另一方面,由于Df2不完整,因此它不会拥有所有数据(A、B、C、D、E)。它仅包含部分数据,例如。在本例中为 A、D、E,因此数据框将如下所示

| Ultimate Parent | Parent | Child |
| --------------- | ------ |-------|
| A               | D      | E     |

现在我想 (1) 使用 Df1 获得正确/完整的层次结构 (2) 比较并识别 Df1 和 Df2 之间的差距。逻辑如下:

如果 A 拥有 B 拥有 C 拥有 D 拥有 E 并且 Df1 看起来像这样

| Ultimate Parent | Parent | Child |
| --------------- | ------ |-------|
| A               | B      | C     |
| C               | D      | E     |

我想添加 1 列将所有相关实体放在一起,并按从最终父级到子级的顺序

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

然后将此 Df1 与 Df2 进行比较,并在 Df2 中添加一列来标识差距。最理想(但可选)的情况是有另一列,说明错误的原因。

| Ultimate Parent | Parent | Child | Right/Wrong| Reason(Optional)|
| --------------- | ------ |-------|------------|-----------------|
| A               | D      | E     | Right      |                 |
| C               | B      | A     | Wrong      | wrong hierarchy |
| A               | F      | G     | Wrong      | wrong entities  |

我尝试过多种字符串匹配方法,但我陷入了我认为顺序很重要的步骤和想法,但我不知道当字符串相关但分散在不同的行中时如何按顺序比较字符串。如有任何帮助,我们将不胜感激。

python pandas hierarchy string-matching
1个回答
0
投票

基本上,您需要构建 df1 的网络图才能获得层次结构的理解图。完成此操作后,您需要将 df2 的层次结构与 df1 的层次结构进行比较并最终进行验证。为此,您可以定义函数。您将为 df1 创建一个新列

hierarchies
,并为 df2 创建一个新列
Right/Wrong
Reason
。请注意,我相信您预期输出中的最后一行是错误的。

import pandas as pd
import networkx as nx

# Define the data for Df1 and 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():
    G.add_edge(row['Parent'], row['Child'])
    if row['Ultimate Parent'] != row['Parent']:  
        G.add_edge(row['Ultimate Parent'], row['Parent'])

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))

def validate_row(row, hierarchy_df):
    filtered_hierarchy = hierarchy_df[hierarchy_df['Ultimate Parent'] == row['Ultimate Parent']]
    if filtered_hierarchy.empty:
        return pd.Series(["Wrong", "wrong entities"])  
    
    full_hierarchy = filtered_hierarchy.iloc[0]['Hierarchy']
    
    if f"{row['Parent']}, {row['Child']}" in full_hierarchy:
        return pd.Series(["Right", ""])  
    else:
        return pd.Series(["Wrong", "wrong hierarchy"])  

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

print("Df1 - Complete Hierarchy:")
print(df1)
print("\nDf2 - Validation Results:")
print(df2)

这给了你

Df1 - Complete Hierarchy:
  Ultimate Parent Parent Child      Hierarchy
0               A      B     C  A, B, C, D, E
1               C      D     E        C, D, E

Df2 - Validation Results:
  Ultimate Parent Parent Child Right/Wrong           Reason
0               A      D     E       Right                 
1               C      B     A       Wrong  wrong hierarchy
2               A      F     G       Wrong  wrong hierarchy
© www.soinside.com 2019 - 2024. All rights reserved.