一个最直接的方法如下,最后得到的s2
就是一个普通的pandas.DataFrame
,可以继续处理:
import pandas as pd
df = pd.DataFrame({'A': ['foo', 'foo', 'foo', 'baz', 'baz', 'baz'],
'B': ['app', 'app', 'cat', 'cat', 'dog', 'dog'],
'C': [1, 2, 3, 4, 5, 6],
'D': [7, 8, 9, 10, 11, 12]})
s1 = df.groupby(["A", "B"]).sum()
s2 = s1.reset_index()
# s2 will be:
# A B C D
# 0 baz cat 4 10
# 1 baz dog 11 23
# 2 foo app 3 15
# 3 foo cat 3 9
# 也可以用 agg 函数,可以指定更多的汇总方式
s3 = df.groupby(["A", "B"]).agg({"C": sum, "D": "mean"}).reset_index()
但如果我们直接求和或者求和的列有文本列,文本列也会被直接加起来或者被过滤掉,这和某些时候的预期不符,比如下面两个处理:
s4 = df.groupby("A").sum().reset_index()
# s4 will be (column B is missing):
# A C D
# 0 baz 15 33
# 1 foo 6 24
s5 = df.sum()
# s5 will be (column A and B is concat)
# A foofoofoobazbazbaz
# B appappcatcatdogdog
# C 21
# D 57
# dtype: object
很多时候我们的需求是:
- 文本列不会被直接加起来(如果数据多,直接加起来是一个很长很长的结果)
- 文本列也不会被过滤,最好显示为指定值,比如'合计'。
第一个需求可以参考sum
的numeric_only
参数,第二个需求则需要更细致的处理,先扩充列再将 None 替换成「合计」:
s4 = df.groupby("A").sum().reset_index()
s4 = s4.reindex(df.columns).fillna("合计")
s6 = df.sum(numeric_only=True)
s6 = s6.reindex(df.columns).fillna("合计")
如果想实现更复杂的
import pandas as pd
# 创建示例 DataFrame
df = pd.DataFrame({
'Group': ['A', 'B', 'A', 'B', 'A'],
'Value1': [1, 2, 3, 4, 5],
'Value2': [10, 20, 30, 40, 50]
})
# 自定义加权平均的聚合函数
def weighted_avg(x):
return (x['Value1'] * x['Value2']).sum() / x['Value2'].sum()
# 使用 groupby() 和 apply() 方法进行分组和同时计算加权平均和平均值
result = df.groupby('Group').apply(lambda x: pd.Series({'Mean': x['Value1'].mean(), 'Weighted Avg': weighted_avg(x)}))
print(result)
Q. E. D.