如何高效统计DataFrame中指定员工的下属人数(含多层级)
高效统计多层级员工下属人数方案
针对大数据量、多层级的员工-上级DataFrame,原始字典循环效率低下的问题,推荐两种高效方案:
方案一:用NetworkX构建有向图(推荐大数据量场景)
NetworkX内置了优化的图遍历算法,能快速获取节点的所有后代(含间接下属),时间复杂度接近O(n+m)(n为员工数,m为上下级关系数),远优于嵌套循环的O(n²)。
代码示例
import networkx as nx import pandas as pd # 示例DataFrame(替换为你的真实数据) df = pd.DataFrame({ 'Employee': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'], 'Manager': [None, 'A', 'A', 'A', 'A', 'B', 'B', 'C', 'C'] }) # 1. 构建有向图:上级→下属的边 G = nx.DiGraph() G.add_nodes_from(df['Employee']) # 过滤无上级的顶层节点,添加合法的上下级边 valid_edges = df.dropna(subset=['Manager'])[['Manager', 'Employee']].values.tolist() G.add_edges_from(valid_edges) # 2. 统计每个员工的下属数及具体名单 subordinate_stats = {} for emp in df['Employee']: descendants = list(nx.descendants(G, emp)) subordinate_stats[emp] = { 'count': len(descendants), 'subordinates': descendants } # 3. 输出结果(按需求格式化) for emp, stats in subordinate_stats.items(): if stats['count'] == 0: print(f"{emp}无下属") else: print(f"{emp}有{stats['count']}名下属({', '.join(stats['subordinates'])})")
优势
- 底层算法优化,处理十万级以上数据依然高效
- 一行代码
nx.descendants即可获取所有间接下属,无需手动实现遍历逻辑 - 可快速扩展其他需求(比如检测层级循环、生成层级路径等)
方案二:手动实现广度优先遍历(BFS,无第三方依赖)
如果不想引入NetworkX依赖,可预先构建「上级→直接下属」的映射字典,再用迭代式BFS遍历所有层级,避免递归栈溢出,同时效率远高于原始循环。
代码示例
import pandas as pd # 示例DataFrame(替换为你的真实数据) df = pd.DataFrame({ 'Employee': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'], 'Manager': [None, 'A', 'A', 'A', 'A', 'B', 'B', 'C', 'C'] }) # 1. 构建上级到直接下属的映射字典 manager_to_direct_subs = df.groupby('Manager')['Employee'].apply(list).to_dict() # 2. 遍历每个员工,用BFS统计所有下属(含间接) subordinate_stats = {} for emp in df['Employee']: total = 0 subs_list = [] queue = manager_to_direct_subs.get(emp, []).copy() total += len(queue) subs_list.extend(queue) while queue: current_sub = queue.pop(0) # 获取当前下属的直接下属 next_level_subs = manager_to_direct_subs.get(current_sub, []) total += len(next_level_subs) subs_list.extend(next_level_subs) queue.extend(next_level_subs) subordinate_stats[emp] = { 'count': total, 'subordinates': subs_list } # 3. 输出结果 for emp, stats in subordinate_stats.items(): if stats['count'] == 0: print(f"{emp}无下属") else: print(f"{emp}有{stats['count']}名下属({', '.join(stats['subordinates'])})")
优势
- 无需额外安装库,代码轻量
- 迭代式BFS避免了递归深度限制,适合极多层级的场景
- 预先构建映射字典,避免重复遍历整个DataFrame,效率提升明显
注意事项
- 层级循环处理:如果数据存在循环(如A是B的上级,B是A的上级),两种方案都会陷入死循环。可先通过
nx.is_directed_acyclic_graph(G)(NetworkX方案)或手动检测的方式清理数据。 - 顶层节点:确保处理
Manager为None的顶层员工,避免遗漏统计。
内容的提问来源于stack exchange,提问作者Bruno Ramos Martins
相关产品推荐
相关产品推荐

