如何按category类型对列求和并保留零值(含DataFrame示例)
如何按category类型对列求和并保留零值(含DataFrame示例)
我来帮你搞定这个需求!从你给出的输入和输出来看,核心是要把分散在Id和Category下的小时数,汇总成每个Id对应不同类别(A/B)的小时数,还得自动给没有对应类别的Id补0,同时保持Id的原始顺序对吧?
先把你的数据用代码还原出来,方便演示:
原始输入DataFrame
import pandas as pd df = pd.DataFrame({ 'Id': [1, 1, 1, 2, 2, 3], 'Category': ['A', 'A', 'B', 'A', 'B', 'A'], 'Hours': [1, 3, 4, 2, 6, 3] })
你期望的输出
Id Total Hours A_Hours B_Hours 0 1 8 4 4 # 这里提一句:你给出的示例里Total Hours写的是5,应该是笔误哦,实际是4+4=8 1 2 8 2 6 2 3 3 3 0
下面给你两种简洁的实现方法,都能完美满足需求:
方法一:Groupby + Unstack 组合法
这个方法逻辑清晰,分步操作容易理解:
# 1. 按Id和Category分组,对Hours求和,再把Category转成列,缺失值补0 grouped = df.groupby(['Id', 'Category'])['Hours'].sum().unstack(fill_value=0) # 2. 给类别列加上_Hours后缀,符合你的输出命名 grouped = grouped.rename(columns={'A': 'A_Hours', 'B': 'B_Hours'}) # 3. 计算Total Hours列,就是A和B的小时数之和 grouped['Total Hours'] = grouped['A_Hours'] + grouped['B_Hours'] # 4. 调整结构:把Id从索引变回普通列,再调整列的顺序 result = grouped.reset_index()[['Id', 'Total Hours', 'A_Hours', 'B_Hours']] print(result)
方法二:Pivot_table 一步到位法
Pandas的pivot_table天生就适合做这种行列转换+汇总的工作,代码更紧凑:
result = pd.pivot_table( df, index='Id', # 按Id分组 columns='Category', # 把Category转成列 values='Hours', # 要汇总的字段是Hours aggfunc='sum', # 汇总方式是求和 fill_value=0 # 缺失的类别自动补0 ) # 重命名列、计算Total Hours、调整列顺序 result = result.rename(columns={'A': 'A_Hours', 'B': 'B_Hours'}) result['Total Hours'] = result.sum(axis=1) result = result.reset_index()[['Id', 'Total Hours', 'A_Hours', 'B_Hours']] print(result)
为什么这个方法能解决你的问题?
- 自动补0:不管是
unstack(fill_value=0)还是pivot_table(fill_value=0),都会自动给某个Id下不存在的Category填充0,完美解决你需要的零值保留需求; - 保持顺序:因为我们是基于原始数据的Id分组,最终的Id顺序会和原始数据中首次出现的顺序一致(这里就是1→2→3);
- 扩展性强:如果之后你的Category新增了C、D之类的类别,代码不需要修改,会自动把新类别转成对应的列并补0。
备注:内容来源于stack exchange,提问作者hailthedawn
相关产品推荐
相关产品推荐

