gpt4 book ai didi

python - Pandas :展平树结构

转载 作者:行者123 更新时间:2023-12-05 09:05:45 25 4
gpt4 key购买 nike

我有一个由以下表示的类别树。

import pandas as pd

asset_tree = [
{'id': 1, 'name': 'Linear Asset', 'parent_id': -1},
{'id': 2, 'name': 'Lateral', 'parent_id': 1},
{'id': 3, 'name': 'Main', 'parent_id': 1},
{'id': 4, 'name': 'Point Asset', 'parent_id': -1},
{'id': 5, 'name': 'Fountain', 'parent_id': 4},
{'id': 6, 'name': 'Hydrant', 'parent_id': 4}
]
tree = pd.DataFrame(asset_tree)
print(tree)

这给了我一个如下的数据框:

   id          name  parent_id
0 1 Linear Asset -1
1 2 Lateral 1
2 3 Main 1
3 4 Point Asset -1
4 5 Fountain 4
5 6 Hydrant 4

树中最高的节点的 parent_id 等于 -1,因此树可以用图形表示如下:

Linear Asset
| - Lateral
| - Main
Point Asset
| - Fountain
| - Hydrant

我需要生成以下数据框。

   id          name  parent_id  flat_name
0 1 Linear Asset -1 Linear Asset
1 2 Lateral 1 Linear Asset : Lateral
2 3 Main 1 Linear Asset : Main
3 4 Point Asset -1 Point Asset
4 5 Fountain 4 Point Asset : Fountain
5 6 Hydrant 4 Point Asset : Hydrant

树是动态生成的,可以有任意数量的层次,所以下面的树

asset_tree = [
{'id': 1, 'name': 'Linear Asset', 'parent_id': -1},
{'id': 2, 'name': 'Lateral', 'parent_id': 1},
{'id': 3, 'name': 'Main', 'parent_id': 1},
{'id': 4, 'name': 'Point Asset', 'parent_id': -1},
{'id': 5, 'name': 'Fountain', 'parent_id': 4},
{'id': 6, 'name': 'Hydrant', 'parent_id': 4},
{'id': 7, 'name': 'Steel', 'parent_id': 2},
{'id': 8, 'name': 'Plastic', 'parent_id': 2},
{'id': 9, 'name': 'Steel', 'parent_id': 3},
{'id': 10, 'name': 'Plastic', 'parent_id': 3}
]

应该产生以下结果:

   id          name  parent_id  flat_name
0 1 Linear Asset -1 Linear Asset
1 2 Lateral 1 Linear Asset : Lateral
2 3 Main 1 Linear Asset : Main
3 4 Point Asset -1 Point Asset
4 5 Fountain 4 Point Asset : Fountain
5 6 Hydrant 4 Point Asset : Hydrant
6 7 Steel 2 Linear Asset : Lateral : Steel
7 8 Plastic 2 Linear Asset : Lateral : Plastic
8 9 Steel 3 Linear Asset : Main : Steel
9 10 Plastic 3 Linear Asset : Main : Plastic

最佳答案

这是一个递归的 apply 函数来完成这个。该函数接受一个 id 并返回它在树中的“路径”:

def flatname(ID):
row = df[df['id'] == ID].squeeze()
if row['parent_id'] == -1:
return row['name']
else:
return flatname(row['parent_id']) + ' : ' + row['name']

要使用,调用:

df['flat_name'] = df['id'].apply(flatname)

第二个例子中使用的df:

   id          name  parent_id                         flat_name
0 1 Linear Asset -1 Linear Asset
1 2 Lateral 1 Linear Asset : Lateral
2 3 Main 1 Linear Asset : Main
3 4 Point Asset -1 Point Asset
4 5 Fountain 4 Point Asset : Fountain
5 6 Hydrant 4 Point Asset : Hydrant
6 7 Steel 2 Linear Asset : Lateral : Steel
7 8 Plastic 2 Linear Asset : Lateral : Plastic
8 9 Steel 3 Linear Asset : Main : Steel
9 10 Plastic 3 Linear Asset : Main : Plastic

OP 注意到上面的函数明确引用了在函数作用域之外定义的 df 变量。因此,如果您将 DataFrame 命名为不同的名称,或者您想在许多 DataFrame 上调用它,这可能会导致问题。一种解决方法是将 apply 函数变成更多的私有(private)助手,并创建一个调用它的外部(对用户更友好的)函数:

def _flatname_recurse(ID, df):
row = df[df['id'] == ID].squeeze()
if row['parent_id'] == -1:
return row['name']
else:
return _flatname_recurse(row['parent_id'], df=df) + ' : ' + row['name']

# asset_df to specify we are looking for a specific kind of df
def flatnames(asset_df):
return asset_df['id'].apply(_flatname_recurse, df=asset_df)

然后调用:

df['flat_name'] = flatnames(df)

另外,请注意我曾经使用 row = df.iloc[ID - 1, :] 来识别行,这在这种情况下有效但依赖于 id 比索引大一。 This approach更通用。

关于python - Pandas :展平树结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66784106/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com