详解Pandas分组函数groupby

这篇具有很好参考价值的文章主要介绍了详解Pandas分组函数groupby。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在数据分析时,经常需要将数据分成不同的群组,pandas中的groupby()函数可以完美地完成各种分组操作。

分组是根据DataFrame/Series的某个字段值,将该字段的值相等的行/列分到同一组中,每一个小组是一个新的DataFrame或Series。

groupby()也可以按DataFrame中的多个字段分组,当多个字段的值都相等时分到同一组。

groupby()经常与批处理函数apply()、聚合函数agg()等配合使用,实现对数据的多元处理。

groupby用法和参数介绍


groupby(self, by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=no_default, observed=False, dropna=True):

  • by: 指定根据哪个/哪些字段分组,默认值是None,按多个字段分组时传入列表。by参数可以按位置参数的方式传入。

  • axis: 设置按列分组还是按行分组,0或index表示按列分组,1或columns表示按行分组,默认值为0。

  • level: 当DataFrame的索引为多重索引时,level参数指定用于分组的索引,可以传入多重索引中索引的下标(0,1...)或索引名,多个用列表传入。

level参数不能与by参数同时使用,如果两者同时存在,当by参数传入的是多重索引中的索引,则level不生效,当by参数传入的是DataFrame的列名,则报错。

  • as_index: 分组结果默认将分组列的值作为索引,如果按单列分组,结果默认是单索引,如果按多列分组,结果默认是多重索引。将as_index设置为False可以重置索引(0,1...)。

  • sort: 结果按分组列的值升序排列,将sort设置为False则不排序,可以提升性能。

  • dropna: 默认情况下,分组列的NaN在分组结果中不保留,将dropna设置为False,可以保留NaN分组。

其他三个参数不用关注,group_keys参数在源码中未使用,squeeze参数因为类型不兼容,官方已弃用,observed参数表示重设索引时,保留创建的全NaN行。

分组对象的内部结构


# coding=utf-8
import pandas as pd
import numpy as np

vip_df = pd.DataFrame(
    {'isVip': ['vip', 'svip', 'member', 'vip', 'member', 'vip', 'svip'],
     'gender': ['male', 'female', 'female', 'female', 'male', 'female', 'male'],
     'age': [25, 30, 40, 25, 40, 18, 30],
     'vipLevel': ['LV2', 'LV5', np.nan, 'LV3', 'LV2', 'LV2', 'LV3'],
     'growValue': [180, 425, np.nan, 288, 190, 110, 240]}
)
print(vip_df)
grouped = vip_df.groupby('isVip')
print(grouped)
    isVip  gender  age vipLevel  growValue
0     vip    male   25      LV2      180.0
1    svip  female   30      LV5      425.0
2  member  female   40      NaN        NaN
3     vip  female   25      LV3      288.0
4  member    male   40      LV2      190.0
5     vip  female   18      LV2      110.0
6    svip    male   30      LV3      240.0
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001C3E81D1370>

groupby()分组得到的是一个DataFrameGroupBy对象,直接打印DataFrameGroupBy对象只能看到它的内存地址,看不到内部的结构。

for name, group in grouped:
    print(name)
    print(group)
member
    isVip  gender  age vipLevel  growValue
2  member  female   40      NaN        NaN
4  member    male   40      LV2      190.0
svip
  isVip  gender  age vipLevel  growValue
1  svip  female   30      LV5      425.0
6  svip    male   30      LV3      240.0
vip
  isVip  gender  age vipLevel  growValue
0   vip    male   25      LV2      180.0
3   vip  female   25      LV3      288.0
5   vip  female   18      LV2      110.0
for group in grouped:
    print(group)
    print(type(group), type(group[0]), type(group[1]))
('member',     isVip  gender  age vipLevel  growValue
2  member  female   40      NaN        NaN
4  member    male   40      LV2      190.0)
<class 'tuple'> <class 'str'> <class 'pandas.core.frame.DataFrame'>
('svip',   isVip  gender  age vipLevel  growValue
1  svip  female   30      LV5      425.0
6  svip    male   30      LV3      240.0)
<class 'tuple'> <class 'str'> <class 'pandas.core.frame.DataFrame'>
('vip',   isVip  gender  age vipLevel  growValue
0   vip    male   25      LV2      180.0
3   vip  female   25      LV3      288.0
5   vip  female   18      LV2      110.0)
<class 'tuple'> <class 'str'> <class 'pandas.core.frame.DataFrame'>

DataFrameGroupBy是一个可迭代对象,可以转换成list打印,也可以直接遍历打印出来。遍历出来的是一个个元组,每个元组对应一个分组,元组的第一个元素与分组列里的值对应,元组的第二个元素是分到当前小组的数据,是一个DataFrame。

DataFrameGroupBy对象的内部结构为:[(分组名1, 子DataFrame1), (分组名2, 子DataFrame2), ...],相当于groupby()将DataFrame按字段值分成了多个小的DataFrame,然后将字段值和小的DataFrame用元组的方式保存在DataFrameGroupBy对象中。

print(grouped.groups)
group_name = [gn for gn in grouped.groups.keys()]
print(group_name)
group = grouped.get_group(group_name[2])
print('-'*40, '\n', group, sep='')
{'member': [2, 4], 'svip': [1, 6], 'vip': [0, 3, 5]}
['member', 'svip', 'vip']
----------------------------------------
  isVip  gender  age vipLevel  growValue
0   vip    male   25      LV2      180.0
3   vip  female   25      LV3      288.0
5   vip  female   18      LV2      110.0

分组对象的groups属性可以返回分组信息,结果是一个形似字典的对象,由分组名和此分组数据在原DataFrame中的行索引组成。

借用groups可以提取出所有分组的分组名,分组对象的get_group()方法可以返回指定分组名的子DataFrame。

按多重索引分组


vip_multi_df = vip_df.set_index(['isVip', 'gender'])
print('-'*40, '\n', vip_multi_df, sep='')
----------------------------------------
               age vipLevel  growValue
isVip  gender                         
vip    male     25      LV2      180.0
svip   female   30      LV5      425.0
member female   40      NaN        NaN
vip    female   25      LV3      288.0
member male     40      LV2      190.0
vip    female   18      LV2      110.0
svip   male     30      LV3      240.0
# 按多重索引中的指定索引进行分组
grouped = vip_multi_df.groupby(level='isVip')
print('-'*40, '\n', grouped.mean(), sep='')
# 按多重索引中除指定索引之外的索引分组
grouped = vip_multi_df.groupby(level=vip_multi_df.index.names.difference(['gender']))
print('-'*40, '\n', grouped.mean(), sep='')
# 按多重索引中的多个索引分组
grouped = vip_multi_df.groupby(level=[0, 1])
print('-'*40, '\n', grouped.mean(), sep='')
----------------------------------------
              age   growValue
isVip                        
member  40.000000  190.000000
svip    30.000000  332.500000
vip     22.666667  192.666667
----------------------------------------
              age   growValue
isVip                        
member  40.000000  190.000000
svip    30.000000  332.500000
vip     22.666667  192.666667
----------------------------------------
                age  growValue
isVip  gender                 
member female  40.0        NaN
       male    40.0      190.0
svip   female  30.0      425.0
       male    30.0      240.0
vip    female  21.5      199.0
       male    25.0      180.0

level参数用于设置按多重索引中的指定索引分组,level传入的方式可以是索引name,也可以是索引在多重索引中的下标,还可以是排除某个索引外的其他索引。指定多个时用列表的方式传入。

grouped = vip_multi_df.groupby('gender')
print('-'*40, '\n', grouped.mean(), sep='')
grouped = vip_multi_df.groupby(['gender', 'age'])
print('-'*40, '\n', grouped.mean(), sep='')
----------------------------------------
              age   growValue
gender                       
female  28.250000  274.333333
male    31.666667  203.333333
----------------------------------------
            growValue
gender age           
female 18       110.0
       25       288.0
       30       425.0
       40         NaN
male   25       180.0
       30       240.0
       40       190.0

多重索引中的索引也可以传给groupby()的by参数,分组结果与将多重索引作为DataFrame的列是一样的。

如果用DataFrame的列作为分组列,多重索引会被转换成列保留在结果中。也可以用多重索引中的索引与列一起组合分组,相当于先对DataFrame重设索引再分组。

重置结果的索引


grouped = vip_multi_df.groupby(['isVip', 'gender'])
print('-'*40, '\n', grouped.mean(), sep='')
# 重设索引
grouped = vip_multi_df.groupby(['isVip', 'gender'], as_index=False)
print('-'*40, '\n', grouped.mean(), sep='')
----------------------------------------
                age  growValue
isVip  gender                 
member female  40.0        NaN
       male    40.0      190.0
svip   female  30.0      425.0
       male    30.0      240.0
vip    female  21.5      199.0
       male    25.0      180.0
----------------------------------------
    age  growValue
0  40.0        NaN
1  40.0      190.0
2  30.0      425.0
3  30.0      240.0
4  21.5      199.0
5  25.0      180.0

分组结果的索引默认是分组列的值,将as_index设置为False可以重置索引,相当于先分组再调用reset_index()函数。

结果是否排序


grouped = vip_df.groupby('isVip')
print('-'*40, '\n', grouped.mean(), sep='')
grouped = vip_df.groupby('isVip', sort=False)
print('-'*40, '\n', grouped.mean(), sep='')
----------------------------------------
              age   growValue
isVip                        
member  40.000000  190.000000
svip    30.000000  332.500000
vip     22.666667  192.666667
----------------------------------------
              age   growValue
isVip                        
vip     22.666667  192.666667
svip    30.000000  332.500000
member  40.000000  190.000000

groupby()默认对结果按分组列的值升序排列,如果将sort参数修改为False,则不排序,保留原DataFrame中的顺序,不排序可以提升性能。

是否保留空值


grouped = vip_df.groupby('vipLevel')
print('-'*40, '\n', grouped.mean(), sep='')
grouped = vip_df.groupby('vipLevel', dropna=False)
print('-'*40, '\n', grouped.mean(), sep='')
----------------------------------------
                age  growValue
vipLevel                      
LV2       27.666667      160.0
LV3       27.500000      264.0
LV5       30.000000      425.0
----------------------------------------
                age  growValue
vipLevel                      
LV2       27.666667      160.0
LV3       27.500000      264.0
LV5       30.000000      425.0
NaN       40.000000        NaN

当分组列有空值(NaN)时,默认的分组结果中不保留NaN分组,将dropna参数修改为False,正常保留NaN分组。

提取分组结果的指定列


grouped = vip_df.groupby('isVip', dropna=False)
print('-'*40, '\n', grouped['gender'], sep='')
for name, group in grouped['gender']:
    print(name)
    print(group)
----------------------------------------
<pandas.core.groupby.generic.SeriesGroupBy object at 0x00000285CA1B0790>
member
2    female
4      male
Name: gender, dtype: object
svip
1    female
6      male
Name: gender, dtype: object
vip
0      male
3    female
5    female
Name: gender, dtype: object

从groupby()分组结果中取一列,得到的是一个SeriesGroupBy对象,直接打印SeriesGroupBy对象只能看到它的内存地址,看不到内部的结构。

SeriesGroupBy的内部结构与DataFrameGroupBy相似,SeriesGroupBy对象的内部结构为:[(分组名1, 子Series1), (分组名2, 子Series2), ...],因此SeriesGroupBy也可以转换成list打印,也可以遍历取出每一个元素。

grouped = vip_df['gender'].groupby(vip_df['isVip'])
for name, group in grouped:
    print(name)
    print(group)
member
2    female
4      male
Name: gender, dtype: object
svip
1    female
6      male
Name: gender, dtype: object
vip
0      male
3    female
5    female
Name: gender, dtype: object

也可以先指定需要获取的列,再按DataFrame的另一个列进行分组,结果与先分组再获取指定列相同。

以上就是pandas中groupby()函数的用法介绍和分析,本文都是用DataFrame举例,Series的用法相似,不重复了。文章来源地址https://www.toymoban.com/news/detail-780713.html

到了这里,关于详解Pandas分组函数groupby的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • pandas数据分析——groupby得到分组后的数据

    Pandas怎样实现groupby聚合后字符串列的合并(四十) pandas—groupby如何得到分组里的数据 在处理时间序列的数据中,有时候会遇到有些日期的数据缺失的情况,这时候可以用pandas的 date_range 函数快速补齐缺失日期,再根据实际情况补齐缺失值。 常用参数为: start :指定生成时

    2024年02月11日
    浏览(36)
  • Java8 Stream分组groupBy后,取单一字段值、取列表第一个值方式

    java8 Stream中groupBy的拓展用法。 取单一字段值、取列表第一个值方式

    2024年02月14日
    浏览(38)
  • python DataFrame数据分组统计groupby()函数

    df = pd.DataFrame(data=data, index=index, columns=columns) print(df) print(“=================================================”) df1 = df.groupby([‘class_1’, ‘class_2’]).sum() # 分组统计求和 print(df1) 1.3 对DataFrameGroupBy对象列名索引(对指定列统计计算) 其中,df.groupby(‘class_1’)得到一个DataFrameGroupBy对象,

    2024年04月25日
    浏览(32)
  • Python中groupby函数详解(非常容易懂)

    groupby函数主要的作用是进行数据的分组以及分组后地组内运算! 于数据的分组和分组运算主要是指groupby函数的应用,具体函数的规则如下: 举例如下: 上面语句的功能是输出表格所有数据中不同地区不同类型的评分数据平均值。 结果为: 首先,我们有一个变量data,数据

    2024年01月16日
    浏览(48)
  • sql 分组讨论,二级分组(非2个字段分组),使用 窗口函数和普通分组实现

    先按照一个字段分组,在按照 第二个字段分组。 之后,如果 这个 二级分组中的数据,是 1条的。就筛选出来。 比如: 先按照 站点分组,再按照 设备分组, 即:如果站点上配置了2个设备。就筛选出来。 然后:这2个设备 都必须是屏幕 查出配置了2个设备的站点 要求 这两个

    2024年02月13日
    浏览(35)
  • java根据分组函数GroupingBy进行多个条件组合分组

    在SQL中经常会用到分组,我们也常常遇到一些组合分组的场景。 java8分组 传统写法(单个字段分组) 场景:根据 城市 进行分组 使用的是方法引用:User::getCity 来完成分组 java8分组 传统写法(多个字段分组) 场景:根据 城市,性别进行分组 一般的写法会是下面的这种写法,

    2023年04月19日
    浏览(42)
  • pandas——groupby操作

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 熟练掌握

    2024年02月07日
    浏览(35)
  • pandas笔记:groupby整理

    按照Type 聚类,聚类后将同组的Kg属性合并,求均值 聚合的内容可以是 max, min, mean, unique(唯一值), nunique(唯一值数量),lambda 表达式       按照Type 聚类,聚类后将同组的Kg、Depth属性合并,求均值   重命名的名字=(需要操作的列名,需要的操作名)       参考内容:

    2024年02月16日
    浏览(40)
  • Mysql 合并多个分组。GROUP_CONCAT 函数 及其平替函数

    GROUP_CONCAT 函数用于将一个分组内的多行数据合并成一个字符串,并以指定的分隔符进行分隔。常用于需要将一个分组内的多条数据以字符串的形式展示的情况。语法如下: GROUP_CONCAT(expr [ORDER BY {unsigned_integer | col_name | expr} [ASC | DESC] [, expr ...]] [SEPARATOR str_val]) 其中,expr 表示要

    2024年02月02日
    浏览(52)
  • 【Python】Pandas Groupby操作的25个示例

    在日常的数据分析中,经常需要将数据根据某个(多个)字段划分为不同的群体(group)进行分析,如电商领域将全国的总销售额根据省份进行划分,分析各省销售额的变化情况,社交领域将用户根据画像(性别、年龄)进行细分,研究用户的使用情况和偏好等。在Pandas中,

    2024年02月03日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包