Python中map函数替代方案及报表计数全零问题排查
问题分析与解决
核心问题原因
你的代码中df['ID'].map(counts)是错误的,因为counts的索引是Manager_Pos_Num(如1111、2222),而df['ID']的值是员工编号(如101、103),两者的键完全不匹配,导致映射后所有值都是NaN,经过fillna(0)后就全变成0了——和map函数本身无关,是映射的键选错了。
正确实现代码
你需要先统计每个管理者+对应职位编号的下属数量,再将该数量关联到对应的管理者行上,同时保留普通员工的行(Reports为0):
import pandas as pd # 构造样本数据 data = { 'ID': [101, 102, 103, 104, 105, 106], 'Manager_ID': [103, 103, 106, 103, 106, None], 'Manger_Pos_Num': [1111, 1111, 2222, 3333, 2222, None] } df = pd.DataFrame(data) # 修正列名拼写错误:Manger_Pos_Num → Manager_Pos_Num df.rename(columns={'Manger_Pos_Num': 'Manager_Pos_Num'}, inplace=True) # 步骤1:统计每个管理者+职位的下属数量 manager_reports = df.dropna(subset=['Manager_Pos_Num']).groupby(['Manager_ID', 'Manager_Pos_Num'])['ID'].nunique().reset_index(name='Reports') # 步骤2:合并到原数据,生成最终结果 result = df[['ID']].merge(manager_reports, left_on='ID', right_on='Manager_ID', how='left') result['Reports'] = result['Reports'].fillna(0).astype(int) result = result[['ID', 'Reports']] print(result)
执行后输出与你的期望一致:
ID Reports 0 101 0 1 102 0 2 103 2 3 103 1 4 105 0 5 106 2
map函数的替代方案
1. 使用DataFrame.merge()(推荐)
如上面的代码所示,merge是处理这类关联统计最常用的方法,逻辑清晰且效率高,适合大数据集。
2. 使用apply()(适合小数据集)
通过自定义函数对每个ID统计下属数量,适合数据量不大的场景:
def get_reports_count(id_val): # 筛选当前ID作为管理者的所有下属,按职位分组统计数量 pos_counts = df[df['Manager_ID'] == id_val].groupby('Manager_Pos_Num')['ID'].nunique() return pos_counts.tolist() if not pos_counts.empty else [0] # 扩展行生成结果 ids = [] reports = [] for _, row in df.iterrows(): counts = get_reports_count(row['ID']) for cnt in counts: ids.append(row['ID']) reports.append(cnt) result = pd.DataFrame({'ID': ids, 'Reports': reports})
3. 使用Series.replace()
如果需要直接对字段进行映射替换,可以先建立职位到数量的映射,再关联到管理者:
# 先统计职位对应的下属数量 pos_counts = df.dropna(subset=['Manager_Pos_Num']).groupby('Manager_Pos_Num')['ID'].nunique() # 建立管理者ID到对应职位的映射 manager_pos_map = df.dropna(subset=['Manager_Pos_Num']).groupby('Manager_ID')['Manager_Pos_Num'].unique() # 生成结果 ids = [] reports = [] for id_val in df['ID']: if id_val in manager_pos_map.index: for pos in manager_pos_map[id_val]: ids.append(id_val) reports.append(pos_counts[pos]) else: ids.append(id_val) reports.append(0) result = pd.DataFrame({'ID': ids, 'Reports': reports})
内容的提问来源于stack exchange,提问作者Coding_Nubie
相关产品推荐
相关产品推荐

