zoukankan      html  css  js  c++  java
  • Python学习笔记:groupby+agg+transform+apply

    一、介绍

    日常数据分析中,难免需要将数据根据某个(或者多个)字段进行分组,求聚合值的操作,例如:求班级男女身高的平均值。可以通过 groupby 实现该需求。

    初步认识:df.groupby('name').agg({'price':'sum'}).reset_index()

    使用语法:

    Series.groupby(by=None,
                  axis=0,
                  level=None,
                  as_index=True,
                  sort=True,
                  group_keys=True,
                  dropna=True)
    

    二、groupby实操

    1.构造测试数据集

    import pandas as pd
    import numpy as np
    
    name = ['老王','吕布','孙悟空']
    
    df = pd.DataFrame({
            'name':[name[x] for x in np.random.randint(0, len(name), 9)],
            'salary':np.random.randint(100,1000,9),
            'score':np.random.randint(6,11,9)
            })
    df
    '''
      name  salary  score
    0  孙悟空     719      6
    1   吕布     907      6
    2   吕布     936      9
    3   老王     974      7
    4   吕布     940      7
    5  孙悟空     857      6
    6   老王     230      7
    7   吕布     464      6
    8   老王     557      9
    '''
    

    2.DataFrameGroupBy对象

    • 查看分组对象
    # 数据框分组对象
    groupbying = df.groupby('name')
    groupbying # <pandas.core.groupby.DataFrameGroupBy object at 0x00000000116A12E8>
    
    # 查看类型
    type(groupbying) # pandas.core.groupby.DataFrameGroupBy
    
    # 查看值
    list(groupbying) # 大列表 包含元组对象
    list(groupbying)[0]
    lvbu = list(groupbying)[0] # 元组
    list(lvbu)[0]
    list(lvbu)[1]
    
    • 遍历分组对象
    for name, group in groupbying:
        print(name)
        print(group)
    
    • 选择分组 get_group()
    groupbying.get_group('孙悟空')
    '''
      name  salary  score
    0  孙悟空     719      6
    5  孙悟空     857      6
    '''
    
    • 同一个列名使用不同聚合函数 agg
    df.groupby('name')['score'].agg(['sum','max','min','mean','size']).reset_index()
    '''
      name  sum  max  min      mean  size
    0   吕布   28    9    6  7.000000     4
    1  孙悟空   12    6    6  6.000000     2
    2   老王   23    9    7  7.666667     3
    '''
    
    • 不作为索引
    df.groupby('name', as_index=False)['score'].sum()
    
    df.groupby('name')['score'].sum()
    

    三、常见聚合函数

    Pandas 常用的聚合函数:

    函数 含义
    min/max 最小值、最大值
    sum
    mean 均值
    median 中位数
    std 标准差
    var 方差
    count 计数

    numpy 库方法同样支持,例如:

    • unique 不同元素
    • nunique 不同元素个数(count是所有个数,不去重)

    四、agg聚合操作

    聚合操作是通过 agg 来完成的,可以指定一个或者多个列分别使用不同的聚合函数来聚合。

    • 对单列聚合
    df.groupby('name').agg({'salary':'sum'}).reset_index()
    df.groupby('name')['salary'].sum().reset_index()
    
    • 对多列聚合
    score = df.groupby('name').agg({'salary':'sum',
                                    'score':'mean'}).reset_index()
    score.columns = ['name', 'salary_sum', 'score_mean']
    score
    '''
      name  salary_sum  score_mean
    0   吕布        3247    7.000000
    1  孙悟空        1576    6.000000
    2   老王        1761    7.666667
    '''
    
    df.groupby('name').agg({'salary':'sum', 'score':'mean'}).reset_index().rename(columns={'salary':'salary_sum', 'score':'score_mean'})
    
    • 针对多列并重命名
    # version 0.25 以后才支持这种写法
    df.groupby('name').agg(
            total_score=pd.NamedAgg(column='score', aggfunc='sum'),
            min_salary=pd.NamedAgg(column='salary', aggfunc='min')
    )
    
    • 统计非重复个数
    df.groupby('name').agg({'score':['unique','nunique']}).reset_index()
    '''
      name      score        
               unique nunique
    0   吕布  [6, 9, 7]       3
    1  孙悟空        [6]       1
    2   老王     [7, 9]       2
    '''
    # 多重索引
    

    五、transform函数

    transform 实现添加一列。

    df['salary_mean'] = df.groupby('name')['salary'].transform('mean')
    '''
      name  salary  score  score_mean  salary_mean
    0  孙悟空     719      6    6.000000       788.00
    1   吕布     907      6    7.000000       811.75
    2   吕布     936      9    7.000000       811.75
    3   老王     974      7    7.666667       587.00
    4   吕布     940      7    7.000000       811.75
    5  孙悟空     857      6    6.000000       788.00
    6   老王     230      7    7.666667       587.00
    7   吕布     464      6    7.000000       811.75
    8   老王     557      9    7.666667       587.00
    '''
    

    如果不使用 transform 实现操作。

    avg_salary = df.groupby('name')['salary'].mean().to_dict()
    df['salary_mean2'] = df['name'].map(avg_salary)
    
    • transform 是在原数据的基础上新增一列,agg 是根据分组字段和聚合函数生成新的数据框
    • transform 的数据是填充到分组对象的每列上,而 agg 生成一个新的聚合结果

    六、apply函数

    分组之后的 apply 应用函数,是以分组后的子数据框作为参数传入指定函数的,与数据框中传入的是 Series 稍有不同。

    def get_max_salary(x):
        df = x.sort_values(by='salary', ascending=True)
        return df.iloc[-1, :]
    
    df.groupby('name', as_index=False).apply(get_max_salary)
    
    • apply 的运行效率比 aggtransform 更慢。

    参考链接:图解Pandas的groupby机制

    参考链接:pandas.DataFrame.groupby

    参考链接:Pandas教程 | 超好用的Groupby用法详解

  • 相关阅读:
    向量、矩阵常用范数
    关于HP M451网络连接的资料
    pyqt程序最小化到系统托盘(未测试)
    博客园美化大集合2020最新!不用担心失效问题!
    添加QQ聊天
    关于加密
    python抓取谷歌学术关键词下文章题目
    如何确定网站可否可爬取
    灵狐浏览器
    利用beautifulsoup进行对标签的二次查找-以打印网易云歌单内容为例
  • 原文地址:https://www.cnblogs.com/hider/p/15565331.html
Copyright © 2011-2022 走看看