Python实现:基于经理层级列统计管理者下属团队数量
需求与解决方案
需求描述
现有包含emp_email、mgr_email、mgr_hier_01至mgr_hier_03列的Pandas DataFrame,需新增num_teams_if_mgr列统计管理者下属团队数量,规则如下:
- 直接下属为经理时,每个经理计1个团队
- 直接下属均为普通员工时,计1个团队
- 非管理者计0
当前DataFrame示例
emp_email mgr_email mgr_hier_01 mgr_hier_02 mgr_hier_03 jack@abc.com cook@abc.com CEO@abc.com sandy@abc.com cook@abc.com katy@abc.com cook@abc.com CEO@abc.com sandy@abc.com cook@abc.com panko@abc.com jacob@abc.com CEO@abc.com jacob@abc.com lynne@abc.com jacob@abc.com CEO@abc.com jacob@abc.com tom@abc.com brian@abc.com CEO@abc.com livp@abc.com brian@abc.com grace@abc.com noah@abc.com CEO@abc.com noah@abc.com will@abc.com hugh@abc.com CEO@abc.com hugh@abc.com samson@abc.com sheila@abc.com CEO@abc.com noah@abc.com sheila@abc.com johnson@abc.com nick@abc.com CEO@abc.com nick@abc.com pete@abc.com jody@abc.com CEO@abc.com livp@abc.com jody@abc.com torres@abc.com golio@abc.com CEO@abc.com sandy@abc.com golio@abc.com jody@abc.com livp@abc.com CEO@abc.com livp@abc.com sandy@abc.com CEO@abc.com CEO@abc.com jacob@abc.com CEO@abc.com CEO@abc.com cook@abc.com sandy@abc.com CEO@abc.com sandy@abc.com livp@abc.com CEO@abc.com CEO@abc.com noah@abc.com CEO@abc.com CEO@abc.com hugh@abc.com CEO@abc.com CEO@abc.com brian@abc.com livp@abc.com CEO@abc.com livp@abc.com nick@abc.com CEO@abc.com CEO@abc.com sheila@abc.com noah@abc.com CEO@abc.com noah@abc.com golio@abc.com sandy@abc.com CEO@abc.com sandy@abc.com CEO@abc.com NAN NAN
期望结果DataFrame示例
emp_email mgr_email mgr_hier_01 mgr_hier_02 mgr_hier_03 num_teams_if_mgr jack@abc.com cook@abc.com CEO@abc.com sandy@abc.com cook@abc.com 0 katy@abc.com cook@abc.com CEO@abc.com sandy@abc.com cook@abc.com 0 panko@abc.com jacob@abc.com CEO@abc.com jacob@abc.com 0 lynne@abc.com jacob@abc.com CEO@abc.com jacob@abc.com 0 tom@abc.com brian@abc.com CEO@abc.com livp@abc.com brian@abc.com 0 grace@abc.com noah@abc.com CEO@abc.com noah@abc.com 0 will@abc.com hugh@abc.com CEO@abc.com hugh@abc.com 0 samson@abc.com sheila@abc.com CEO@abc.com noah@abc.com sheila@abc.com 0 johnson@abc.com nick@abc.com CEO@abc.com nick@abc.com 0 pete@abc.com jody@abc.com CEO@abc.com livp@abc.com jody@abc.com 0 torres@abc.com golio@abc.com CEO@abc.com sandy@abc.com golio@abc.com 0 jody@abc.com livp@abc.com CEO@abc.com livp@abc.com 1 sandy@abc.com CEO@abc.com CEO@abc.com 2 jacob@abc.com CEO@abc.com CEO@abc.com 1 cook@abc.com sandy@abc.com CEO@abc.com sandy@abc.com 1 livp@abc.com CEO@abc.com CEO@abc.com 2 noah@abc.com CEO@abc.com CEO@abc.com 1 hugh@abc.com CEO@abc.com CEO@abc.com 1 brian@abc.com livp@abc.com CEO@abc.com livp@abc.com 1 nick@abc.com CEO@abc.com CEO@abc.com 1 sheila@abc.com noah@abc.com CEO@abc.com noah@abc.com 1 golio@abc.com sandy@abc.com CEO@abc.com sandy@abc.com 1 CEO@abc.com NAN NAN 6
已生成经理层级列的代码
import networkx as nx # 创建有向图 G = nx.from_pandas_edgelist(df_hc, source='mgr_email', target='emp_email', create_using=nx.DiGraph) # 找到根节点(最高管理者) roots = [n for n,d in G.in_degree() if d==0] # 为每个员工生成经理层级 df_hierarchy = (pd.DataFrame([next((p for root in roots for p in nx.all_simple_paths(G, root, node)), [])[:-1] for node in df_hc['emp_email']], index= df_hc.index).rename(columns=lambda x: f'mgr_hier_{x+1:02d}')) # 合并到原DataFrame df_hc2 = df_hc.join(df_hierarchy)
实现num_teams_if_mgr列的解决方案
我们可以利用已构建的NetworkX有向图来快速统计团队数量,以下是两种实现方式:
方式一:基于图节点属性与后继节点统计
# 标记每个节点是否为管理者(有下属即出度>0) is_manager = {node: G.out_degree(node) > 0 for node in G.nodes()} # 定义计算团队数量的函数 def get_team_count(emp_email): if not is_manager.get(emp_email, False): return 0 # 获取该管理者的直接下属 direct_subordinates = list(G.successors(emp_email)) # 统计下属中管理者的数量 sub_manager_count = sum(is_manager[sub] for sub in direct_subordinates) # 按规则返回结果:有下属经理则返回数量,否则返回1 return sub_manager_count if sub_manager_count > 0 else 1 # 新增列到DataFrame df_hc2['num_teams_if_mgr'] = df_hc2['emp_email'].apply(get_team_count)
方式二:基于Pandas分组统计
# 获取所有管理者集合(mgr_email中非空值) managers = set(df_hc['mgr_email'].dropna()) # 分组统计每个管理者的直接下属 direct_reports_map = df_hc.groupby('mgr_email')['emp_email'].apply(list).to_dict() # 定义计算函数 def calculate_team_num(emp_email): if emp_email not in managers: return 0 # 获取直接下属列表 reports = direct_reports_map.get(emp_email, []) # 统计下属中的管理者数量 manager_reports = sum(1 for report in reports if report in managers) return manager_reports if manager_reports > 0 else 1 # 应用函数生成新列 df_hc2['num_teams_if_mgr'] = df_hc2['emp_email'].apply(calculate_team_num)
两种方式都能得到符合期望的结果,比如CEO的直接下属有6位经理,所以num_teams_if_mgr为6;sandy的直接下属是cook和golio两位经理,所以值为2,均与示例一致。
内容的提问来源于stack exchange,提问作者wjie08
相关产品推荐
相关产品推荐

