使用 Pandas 数据框对分层 Parent-Child 数据进行分组 - Python

Grouping Herarchical Parent-Child data using Pandas Dataframe - Python

我有一个数据框,我想根据同一数据框中另一列的值对其进行分组。

例如:

Parent_ID 和 Child ID 相互关联,并在层次结构树中定义了谁与谁相关。

数据框看起来像(从 csv 文件输入)

No  Name    ID  Parent_Id
1   Tom     211 111
2   Galie   209 111
3   Remo    200 101
4   Carmen  212 121
5   Alfred  111 191
6   Marvela 101 111
7   Armin   234 101
8   Boris   454 109
9   Katya   109 323

我想在下面的分组中根据 ID 和 Parent_ID 对这个数据框进行分组,并根据顶层 parent 从中生成 CSV 文件。即,Alfred.csv、Carmen.csv(将只有自己的条目,冰线 #4),Katya.csv 使用 to_csv() 函数。

Alfred
  |_ Galie
   _ Tom
   _ Marvela
       |_ Remo
        _ Armin
Carmen
Katya
  |_ Boris

并且,我想在同一个数据框中创建一个新列,该列将有一个指示层次结构的标签。喜欢:

No  Name    ID  Parent_Id   Tag
1   Tom     211 111     Alfred
2   Galie   209 111     Alfred
3   Remo    200 101     Marvela, Alfred
4   Carmen  212 121 
5   Alfred  111 191 
6   Marvela 101 111     Alfred
7   Armin   234 101     Marvela, Alfred
8   Boris   454 109     Katya
9   Katya   109 323

请注意,名称可以重复,但 ID 是唯一的。

请告诉我如何使用 pandas 实现此目的。我尝试了 groupby() 但似乎有点复杂并且没有得到我想要的。每个 parent 应该有一个文件,child 记录在 parent 文件中。 如果 child 有其他 child(如 marvel),它有资格拥有自己的 csv 文件。

最终输出将是

Alfred.csv - All records matching Galie, Tom, Marvela
Marvela.csv - All records matching Remo, Armin
Carmen.csv - Only record matching carmen (row)
Katya.csv - all records matching katya, boris

我会写一个递归函数来做到这一点。

首先,创建{id:name}{parent:id}和递归函数的字典。

id_name_dict = dict(zip(df.ID, df.Name))
parent_dict = dict(zip(df.ID, df.Parent_Id))

def find_parent(x):
    value = parent_dict.get(x, None)
    if value is None:
        return ""
    else:
        # Incase there is a id without name.
        if id_name_dict.get(value, None) is None:
            return "" + find_parent(value)

        return str(id_name_dict.get(value)) +", "+ find_parent(value)

然后使用 Series.apply 创建新列并使用 Series.str.strip

删除 ', '
df['Tag'] = df.ID.apply(lambda x: find_parent(x)).str.rstrip(', ')

df

   No     Name   ID  Parent_Id              Tag
0   1      Tom  211        111           Alfred
1   2    Galie  209        111           Alfred
2   3     Remo  200        101  Marvela, Alfred
3   4   Carmen  212        121                 
4   5   Alfred  111        191                 
5   6  Marvela  101        111           Alfred
6   7    Armin  234        101  Marvela, Alfred
7   8    Boris  454        109            Katya
8   9    Katya  109        323