pandas分组统计 - groupby功能

本文详细介绍Pandas库中DataFrame的groupby功能,包括数据分组、独立应用函数及结果合并,涵盖单列、多列分组,以及通过字典、Series、函数等方式实现灵活分组,最后提供实例演示多种分组计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据分组

分组统计 - groupby功能

① 根据某些条件将数据拆分成组
② 对每个组独立应用函数
③ 将结果合并到一个数据结构中

Dataframe在行(axis=0)或列(axis=1)上进行分组,将一个函数应用到各个分组并产生一个新值,然后函数执行结果被合并到最终的结果对象中。

df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)

注:因为输出结果冗长,请读者自行赋值粘贴到jupyter(推荐)中运行。欢迎评论交流

分组

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
                   'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                   'C' : np.random.randn(8),
                   'D' : np.random.randn(8)})
print(df)
print('------')

print(df.groupby('A'), type(df.groupby('A')))
print('------')
# 直接分组得到一个groupby对象,是一个中间数据,没有进行计算

a = df.groupby('A').mean()
b = df.groupby(['A','B']).mean()
c = df.groupby(['A'])['D'].mean()  # 以A分组,算D的平均值
print("-----------------")
print(a,type(a),'\n',a.columns)
print()
print(b,type(b),'\n',b.columns)
print()
print(c,type(c))
# 通过分组后的计算,得到一个新的dataframe
# 默认axis = 0,以行来分组
# 可单个或多个([])列分组

分组 - 可迭代对象

df = pd.DataFrame({'X' : ['A', 'B', 'A', 'B'], 'Y' : [1, 4, 3, 2]})
print(df)
print(df.groupby('X'), type(df.groupby('X')))
print('-----')

print(list(df.groupby('X')), '→ 可迭代对象,直接生成list\n')
print(list(df.groupby('X'))[0], '→ 以元祖形式显示\n')
for n,g in df.groupby('X'):
    print(n)
    print(g)
    print('###')
print('-----')
# n是组名,g是分组后的Dataframe

print(df.groupby(['X']).get_group('A'),'\n')
print(df.groupby(['X']).get_group('B'),'\n')
print('-----')
# .get_group()提取分组后的组

grouped = df.groupby(['X'])
print(grouped.groups)
print(grouped.groups['A'])  # 也可写:df.groupby('X').groups['A']
print('-----')
# .groups:将分组后的groups转为dict
# 可以字典索引方法来查看groups里的元素

sz = grouped.size()
print(sz,type(sz))
print('-----')
# .size():查看分组后的长度

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
                   'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                   'C' : np.random.randn(8),
                   'D' : np.random.randn(8)})
print(df)
print()
print(df.groupby(['A','B']))
print()
grouped = df.groupby(['A','B']).groups

print(grouped)
print()
print(grouped[('foo', 'three')])
# 按照两个列进行分组

其他轴上的分组

import pandas as pd
import numpy as np

df = pd.DataFrame({'data1':np.random.rand(2),
                  'data2':np.random.rand(2),
                  'key1':['a','b'],
                  'key2':['one','two']})
print(df)
print(df.dtypes)
print("-------------")
print(df.groupby(df.dtypes, axis=1))
print('-----')
print(list(df.groupby(df.dtypes, axis=1)))
print()
for n,p in df.groupby(df.dtypes, axis=1):
    print(n)
    print()
    print(p)
    print('##')
# 按照值类型分列

通过字典或者Series分组

df = pd.DataFrame(np.arange(16).reshape(4,4),
                  columns = ['a','b','c','d'])
print(df)
print('-----')

mapping = {'a':'one','b':'one','c':'two','d':'two','e':'three'}
by_column = df.groupby(mapping, axis = 1)
print(by_column.sum())
print('-----')
# mapping中,a、b列对应的为one,c、d列对应的为two,以字典来分组

s = pd.Series(mapping)
print(s,'\n')
print(s.groupby(s).count())
# s中,index中a、b对应的为one,c、d对应的为two,以Series来分组

通过函数分组

df = pd.DataFrame(np.arange(16).reshape(4,4),
                  columns = ['a','b','c','d'],
                 index = ['abc','bcd','aa','b'])
print(df,'\n')
print(df.groupby(len).sum())
# 按照字母长度分组

分组计算函数方法

s = pd.Series([1, 2, 3, 10, 20, 30], index = [1, 2, 3, 1, 2, 3])
grouped = s.groupby(level=0)  # 唯一索引用.groupby(level=0),将同一个index的分为一组
print(grouped)
print(grouped.first(),'→ first:非NaN的第一个值\n')
print(grouped.last(),'→ last:非NaN的最后一个值\n')
print(grouped.sum(),'→ sum:非NaN的和\n')
print(grouped.mean(),'→ mean:非NaN的平均值\n')
print(grouped.median(),'→ median:非NaN的算术中位数\n')
print(grouped.count(),'→ count:非NaN的值\n')
print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')
print(grouped.std(),'→ std,var:非NaN的标准差和方差\n')
print(grouped.prod(),'→ prod:非NaN的积\n')

多函数计算:agg()

df = pd.DataFrame({'a':[1,1,2,2],
                  'b':np.random.rand(4),
                  'c':np.random.rand(4),
                  'd':np.random.rand(4),})
print(df)
print(df.groupby('a').agg(['mean',np.sum])) 
print(df.groupby('a')['b'].agg({'result1':np.mean,
                               'result2':np.sum}))
# 函数写法可以用str,或者np.方法
# 可以通过list,dict传入,当用dict时,key名为columns

下面是一个测试题,大家可以尝试一下

按要求创建Dataframe df(如下图),并通过分组得到以下结果
① 以A分组,求出C,D的分组平均值
② 以A,B分组,求出D,E的分组求和
③ 以A分组,得到所有分组,以字典显示
④ 按照数值类型分组,求和
⑤ 将C,D作为一组分出来,并计算求和
⑥ 以B分组,求出每组的均值,求和,最大值,最小值

创建的Dataframe

import pandas as pd
import numpy as np

df = pd.DataFrame({"A":["one","two","three","one","two","three","one","two"],
                  "B":(list("hhhh") + list("ffff")),
                   "C":range(10,26,2),
                   "D":np.random.randn(8),
                   "E":np.random.rand(8)
                  })
print(df)
print("----------以A分组,求出CD的分组平均值-------------")
print(df.groupby(["A"], axis = 0)["C","D"])
df1 = df.groupby(["A"], axis = 0)["C","D"].mean()   # 先聚合
print(df1)
print("-----------以AB分组,求DE的分组和--------")
df2 = df.groupby(["A", "B"], axis = 0)["D","E"].sum()   # 先聚合
print(df2)
print("-----------以A分组,得到所有分组的字典--------")
df2 = df.groupby(["A"], axis = 0)
print(df2.groups)
print("按照数值类型分组,求和")
df3 = df.groupby(df.dtypes, axis = 1).sum()
print(df3)
print("----------将CD作为一组分出来,并计算求和-----------")
mapping = {"C":"one", "D":"one"}
print(df.groupby(mapping, axis = 1).sum())
print("------------以B分组,求每一组的均值、和、最大值、最小值-----------------------------------------------------")
print(df.groupby(["B"]).agg([np.mean, np.sum, np.max, np.min]))
### 如何在 Pandas GroupBy 结果中添加列名 当使用 `groupby` 对数据进行分组并应用聚合操作后,有时会发现生成的结果缺少显式的列名。为了确保结果具有清晰的表头,可以通过以下方式来设置或修改列名。 #### 使用 rename 方法重命名 Series 或 DataFrame 的索引名称 如果通过 `groupby().agg()` 得到的是一个 Series,则可以直接转换成 DataFrame 并利用 `rename_axis` 来指定新的轴标签[^1]: ```python import pandas as pd import numpy as np # 创建示例数据集 df = pd.DataFrame({ 'A': ['foo', 'bar', 'foo', 'bar'] * 3, 'B': np.random.randint(0, 100, size=12), }) # 执行 groupby 和 agg 操作 result_series = df.groupby('A')['B'].sum() # 将 Series 转换为 DataFrame 并设置新列名为 "Sum" result_df_with_header = result_series.to_frame(name='Sum') print(result_df_with_header) ``` #### 设置多级索引后的列名 对于更复杂的场景,比如执行多个聚合函数时产生的 MultiIndex 列情况,可以先获取原始列名再重新定义它们[^3]: ```python # 应用多个聚合函数 multi_agg_result = df.groupby('A')['B'].agg([np.size, np.sum, np.mean]) # 获取当前列级别名称 current_columns = multi_agg_result.columns.tolist() new_column_names = ["Count", "Total", "Average"] # 替换原有的列名 final_result = multi_agg_result.set_axis(new_column_names, axis=1) print(final_result) ``` #### 处理复杂嵌套结构的情况 如果有更加复杂的嵌套结构(例如由多重键组成的分组),则可以在调用 `unstack()` 后调整层次化的列名[^5]: ```python complex_grouping = ( df.assign(DummyColumn=1) # 添加辅助列用于 unstack .pivot_table( index=['DummyColumn'], columns=['A'], values='B', aggfunc=[len], fill_value=0 ) .droplevel(level=0, axis=1) # 移除不必要的层级 .reset_index(drop=True) .set_axis(['Foo_Count', 'Bar_Count'], axis=1) # 自定义最终列名 ) print(complex_grouping) ``` 以上三种方法可以根据实际需求灵活运用,在不同的情况下都能有效地为 `groupby` 分组统计的结果添加合适的表头。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值