Python Pandas 获取到高层管理的层级路径
我有一个下面的 pandas 数据框(DF)
创建这个数据框的步骤
data=[['1','0','0','0','0'],['2','1','1','0','0|0'],['3','1','1','1','0|1'],['4','2','2','0','0|0|0'],['5','2','2','1','0|0|1'],['6','2','2','2','0|0|2'],['7','3','2','0','0|1|0'],['8','3','2','1','0|1|1'],['9','3','2','2','0|1|2'],['10','3','2','3','0|1|3'],['11','4','3','0','0|0|0|0'],['12','4','3','1','0|0|0|1'],['13','10','3','0','0|1|3|0']]
df = pd.DataFrame(data, columns=['eid','m_eid','level','path_variable','complete_path'])
df=df.drop('complete_path',axis=1)
这里:
eid = 员工编号
m_eid = 经理编号
level = 在组织中的级别(0 是最高的老板)
path_variable = 根据员工的级别分配的递增编号,这个编号会根据每个经理重置(例如:eid[4,5,6,7,8,9,10] 都属于同一级别 2,但 eid[4,5,6] 有相同的经理(m_eid=2),所以他们的 path_variable 是 0,1,2,而 eid[7,8,9,10] 有不同的经理(m_eid=3),所以 path_variable 从 0 开始重新计数)
我想创建一个新列,显示每个 eid 从最底层到 0 级别的完整路径。就像下面这样:
完整路径是从底层到顶层(最高老板)的 path_variable 的连接。
这就像是从根节点到边缘节点的路径。例如,假设我们看 eid 10
在直接经理之间可能会有级别跳跃。我想避免使用 iterrows(),因为性能方面的限制。
1 个回答
3
如果我理解得没错,你可以使用networkx
来构建一个有向图,然后找到每个节点到'0'
的shortest_path
,接着用这个结果来映射path_variable
:
import networkx as nx
G = nx.from_pandas_edgelist(df, source='m_eid', target='eid',
create_using=nx.DiGraph)
s = df.set_index('eid')['path_variable']
mapper = {n: '|'.join(s.get(x, '') for x in
nx.shortest_path(G, source='0',
target=n)[1:])
for n in df['eid'].unique()
}
df['complete_path'] = df['eid'].map(mapper)
输出结果:
eid m_eid level path_variable complete_path
0 1 0 0 0 0
1 2 1 1 0 0|0
2 3 1 1 1 0|1
3 4 2 2 0 0|0|0
4 5 2 2 1 0|0|1
5 6 2 2 2 0|0|2
6 7 3 2 0 0|1|0
7 8 3 2 1 0|1|1
8 9 3 2 2 0|1|2
9 10 3 2 3 0|1|3
10 11 4 3 0 0|0|0|0
11 12 4 3 1 0|0|0|1
12 13 10 3 0 0|1|3|0
图示:
如果你已经在eid
中有唯一的值,你可以省略映射器,直接使用:
df['complete_path'] = ['|'.join(s.get(x, '') for x in
nx.shortest_path(G, source=n,
target='0')[-2::-1])
for n in df['eid']]
为了让理解更简单,这里有一个更经典的路径,显示的是节点的ID(不是path_variables
):
mapper = {n: '|'.join(nx.shortest_path(G, source='0',
target=n)[1:])
for n in df['eid'].unique()
}
df['complete_path'] = df['eid'].map(mapper)
输出结果:
eid m_eid level path_variable complete_path
0 1 0 0 0 1
1 2 1 1 0 1|2
2 3 1 1 1 1|3
3 4 2 2 0 1|2|4
4 5 2 2 1 1|2|5
5 6 2 2 2 1|2|6
6 7 3 2 0 1|3|7
7 8 3 2 1 1|3|8
8 9 3 2 2 1|3|9
9 10 3 2 3 1|3|10
10 11 4 3 0 1|2|4|11
11 12 4 3 1 1|2|4|12
12 13 10 3 0 1|3|10|13