Pandas动态展平父子层次结构

2024-10-03 13:31:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望动态展平父-子层次结构数据帧

注意事项:

  • 未知级别数
  • 父级可以有两个或多个同名的子级
  • 父母和子女之间的多对多关系(父母可以有多个子女;一个子女可以有来自不同级别的多个父母)
  • 元素的名称未知

输入示例:

import pandas as pd
import numpy as np
pd.options.display.max_columns = None
pd.options.display.max_rows = None
pd.options.display.expand_frame_repr = False
pd.options.mode.chained_assignment = None


df = pd.DataFrame(
    {
        "child": ["xyz", "opr", "axz", "asd", "asd", "zxc", "zxc", "zxc"],
        "parent": [np.nan, "xyz", "xyz", "opr", "opr", "opr", "axz", "xyz"],
    }
)

print(df)

预期输出:

  level_0 level_1 leaf
0     xyz     opr  asd
1     xyz     opr  asd
2     xyz     opr  zxc
3     xyz     axz  zxc
4     xyz     NaN  zxc

Tags: importnoneasdisplaynp级别optionspd
1条回答
网友
1楼 · 发布于 2024-10-03 13:31:23

leaf是child列中不存在的元素

完成后,我将在每次传递时迭代添加一个新的父列,直到所有父列都为NaN。为了确保最后一级包含最终的grand_父级,还需要另一个技巧:如果父列包含NaN,则必须将值与前一列进行切换。代码:

result = df[~df['child'].isin(df['parent'])]
result.columns = ['leaf', 'lev_1']
ix = 1
while True:
    result = result.merge(df, 'left', left_on=f'lev_{ix}', right_on='child'
                          ).drop(columns='child')
    if (result['parent'].isna().all()):
        result = result.drop(columns='parent')
        break
    result.loc[result['parent'].isna(), f'lev_{ix}':'parent'
               ] = result[result['parent'].isna()][['parent', f'lev_{ix}']
                                                   ].values
    print(result)
    ix += 1
    result = result.rename(columns={'parent': f'lev_{ix}'})
# rename and reorder columns to match your expected result
result = result.rename(columns={f'lev_{ix-i}': f'lev_{i}' for i in range(ix)}
                       ).reindex(columns=[f'lev_{i}' for i in range(ix)]
                                 + ['leaf'])

正如预期的那样:

          lev_0     lev_1     leaf
0  grand parent  parent 1  child 1
1  grand parent  parent 1  child 1
2  grand parent  parent 1  child 2
3  grand parent  parent 2  child 2
4  grand parent       NaN  child 2

并且应该接受任意数量的级别

相关问题 更多 >