目录

第10章 数据聚合与分组操作

10.1  GroupBy机制

10.1.1 遍历各分组

10.1.2  选择一列或所有列的子集

10.1.3 使用字典和Series分组

10.1.4 使用函数分组

10.1.5 根据索引层级分组

10.2 数据聚合

10.2.1 逐列及多函数应用

10.2.2 返回不含行索引的聚合数据

10.3 应用:通用拆分-应用-联合

10.3.1 压缩分组键

10.3.2 分位数与桶分析

10.3.3 示例:使用指定分组值填充缺失值

10.3.4 示例:随机采样与排列

10.3.5 示例:分组加权平均和相关性

10.3.6 示例:逐组线性回归

10.4 数据透视表与交叉表

10.4.1 交叉表:crosstab

参考书籍


第10章 数据聚合与分组操作

对数据集进行分类,并在每一组上应用一个聚合函数或转换函数,这通常是数据分析工作流中的一个重要部分。在载入、合并、准备数据集之后,你可能需要计算分组统计或者数据透视表用于报告或可视化的目的。pandas提供一个灵活的groupby接口,允许你以一种自然的方式对数据集进行切片、切块和总结。

在本章,你将学习如何:

  · 使用一个或多个键(以函数、数组或DataFrame列名的形式)将pandas对象拆分为多块

 · 计算组汇总统计信息,如计数、平均值或标准偏差或用户定义的函数

 · 应用组内变换或其他操作,如标准化、线性回归、排位或子集选择

 · 计算数据透视表和交叉表

  · 执行分位数分析和其他统计组分析

10.1  GroupBy机制

简单的分组聚合样例:

示例,一个小型表格数据集作为DataFrame的例子:

假设你想要根据key1标签计算data1列的均值,有多种方法可以实现。

其中一种是访问data1并使用key1列(它是一个Series)调用groupby方法:

grouped变量现在是一个GroupBy对象。

除了一些关于分组键df['key1']的一些中间数据之外,它实际上还没有进行任何计算。这个对象拥有所有必需的信息,之后可以在每一个分组上应用一些操作。

例如,为了计算分组的均值我们可以调用GroupBy的mean方法:

数据(一个Series)根据分组键进行了聚合,并产生了一个新的Series,这个Series使用key1列的唯一值作为索引。由于DataFrame的列df['key1'],结果中的索引名称是’key1'。

如果我们将多个数组作为列表传入,则我们会得到一些不同的结果:

这里我们使用了两个键对数据进行分组,并且结果Series现在拥有一个包含唯一键对的多层索引:

在这个例子中,分组键都是Series,尽管分组键也可以是正确长度的任何数组:

分组信息作为你想要继续处理的数据,通常包含在同一个DataFrame中。

在这种情况下,你可以传递列名(无论那些列名是字符串、数字或其他Python对象)作为分组键:

如果不在意使用groupby的目的,通用的GroupBy方法是size, size方法返回一个包含组大小信息的Series:

注意,分组键中的任何缺失值将被排除在结果之外。

10.1.1 遍历各分组

GroupBy对象支持迭代,会生成一个包含组名和数据块的2维元组序列:

在多个分组键的情况下,元组中的第一个元素是键值的元组:

当然,你可以选择在任何一块数据上进行你想要的操作。

使用一行代码计算出数据块的字典可能会对你有用:

默认情况下,groupby在axis=0的轴向上分组,但你也可以在其他任意轴向上进行分组。

例如,我们可以像以下代码一样,根据dtype对我们的示例df的列进行分组:

打印各分组,如下:

df['data1'].groupby(df['key1'])
df[['data2']].groupby(df['key1'])

10.1.2  选择一列或所有列的子集

将从DataFrame创建的GroupBy对象用列名称或列名称数组进行索引时,会产生用于聚合的列子集的效果。这表明:

df.groupby('key1')['data1']
df.groupby('key1')[['data2']]

是下面代码的语法糖:

df['data1'].groupby(df['key1'])
df[['data2']].groupby(df['key1'])

尤其是对于大型数据集,可能只需要聚合少部分列。

例如,在处理数据集时,要计算data2列的均值,并获得DataFrame形式的结果,可以写:

如果传递的是列表或数组,则此索引操作返回的对象是分组的DataFrame;

如果只有单个列名作为标量传递,则为分组的Series:

10.1.3 使用字典和Series分组

分组信息可能会以非数组形式存在。让我们考虑另一个示例DataFrame:

假设拥有各列的分组对应关系,并且想把各列按组累加:

现在,可以根据这个字典构造传给groupby的数组,但是也可以直接传字典(多写了键’f’用于表明未用的分组键也是没问题的):

Series也有相同的功能,可以视为固定大小的映射:

10.1.4 使用函数分组

与使用字典或Series分组相比,使用Python函数是定义分组关系的一种更为通用的方式。

作为分组键传递的函数将会按照每个索引值调用一次,同时返回值会被用作分组名称。

更具体地说,考虑上一节中的示例DataFrame,其中人的名字作为索引值。假设你想根据名字的长度来进行分组。虽然你可以计算出字符串长度的数组,但传递len函数更为简单:

将函数与数组、字典或Series进行混合并不困难,所有的对象都会在内部转换为数组:

10.1.5 根据索引层级分组

分层索引的数据集有一个非常方便的地方,就是能够在轴索引的某个层级上进行聚合。

示例:

根据层级分组时,将层级数值或层级名称传递给level关键字:

10.2 数据聚合

聚合是指所有根据数组产生标量值的数据转换过程。

之前的例子已经使用了一些聚合操作,包括mean、count、min和sum等。

优化的groupby方法:

可以使用自行制定的聚合,并调用已经在分组对象上定义好的方法。

要使用自己的聚合函数,需要将函数传递给aggregate或agg方法:

自定义聚合函数通常比上边优化函数慢得多。这是因为在构造中间组数据块时有一些额外的开销(函数调用、数据重新排列)

10.2.1 逐列及多函数应用

示例,在使用read_csv载入数据集后,增加一个小费比例列tip-pct::

可能想根据各列同时使用多个函数进行聚合,也是可以实现的。

根据day和smoker来对tips进行分组:

要获得描述性统计,可以将函数名以字符串形式传递:

如果传递的是函数或者函数名的列表,会获得一个列名是这些函数名的DataFrame:

这里传递了聚合函数的列表给agg方法,这些函数会各自运用于数据分组。

你可以不接受GroupBy对象给予各列的名称。请注意,lambda函数具有名称’<lambda>',这使得它们难以识别(你可以查看函数的__name__属性)。

如果你传递的是(name, function)元组的列表,每个元组的第一个元素将作为DataFrame的列名(你可以认为二元元组的列表是一种有序的对应关系):

在DataFrame中,你有更多的选项,你可以指定应用到所有列上的函数列表或每一列上要应用的不同函数。

假设我们想要计算tip_pct列和total_bill列的三个相同的统计值:

将不同的函数应用到一个或多个列上。要实现这个功能,需要将含有列名与函数对应关系的字典传递给agg:

只有多个函数应用于至少一个列时,DataFrame才具有分层列。

10.2.2 返回不含行索引的聚合数据

在前面所有的例子中,聚合数据返回时都是带有索引的,有时索引是分层的,由唯一的分组键联合形成。

因为不是所有的情况下都需要索引,所以在大多数情况下你可以通过向groupby传递as_index=False来禁用分组键作为索引的行为:

当然,通过在结果上调用reset_index也可以获得同样的结果。

10.3 应用:通用拆分-应用-联合

GroupBy方法最常见的目的是apply(应用)。

如图所示, apply将对象拆分成多块,然后在每一块上调用传递的函数,之后尝试将每一块拼接到一起:

继续上边的小费数据集,假设你想要按组选出小费百分比(tip-pct)最高的五组:

首先,写一个可以在特定列中选出最大值所在行的函数:

如果我们按照smoker进行分组,之后调用apply,我们会得到以下结果:

这里发生了什么?top函数在DataFrame的每一行分组上被调用,之后使用pandas.concat将函数结果粘贴在一起,并使用分组名作为各组的标签。因此结果包含一个分层索引,该分层索引的内部层级包含原DataFrame的索引值。

如果你除了向apply传递函数,还传递其他参数或关键字的话,你可以把这些放在函数后进行传递:

除了基础的使用机制,还需要一些创造力才能充分地使用apply。传递函数的内部发生的事情取决于你自己,函数只需要返回一个pandas对象或一个标量值。

在GroupBy对象上调用describe方法:

在GroupBy对象的内部,当你调用像describe这样的方法时,实际上是以下代码的简写:

f = lambda x:x.dexcribe()
grouped.apply(f)

10.3.1 压缩分组键

在之前的例子中,你可以看到所得到的对象具有分组键所形成的分层索引以及每个原始对象的索引。你可以通过向groupby传递group_keys=False来禁用这个功能:

10.3.2 分位数与桶分析

pandas有一些工具,尤其是cut和qcut,用于将数据按照你选择的箱位或样本分位数进行分桶。与groupby方法一起使用这些函数可以对数据集更方便地进行分桶或分位分析。

考虑一个简单的随机数据集和一个使用cut的等长桶分类:

cut返回的Categorical对象可以直接传递给groupby。所以我们可以计算出data2列的一个统计值集合,如下:

这些就是等长桶。

为了根据样本分位数计算出等大小的桶,则需要使用qcut。

我们将传递labels=False来获得分位数数值:

10.3.3 示例:使用指定分组值填充缺失值

在清除缺失值时,有时你会使用dropna来去除缺失值,但是有时你可能想要使用修正值或来自于其他数据的值来输入(填充)到null值(NA)。fillna是一个可以使用的正确工具,例如这里我使用平均值来填充NA值:

假设你需要填充值按组来变化。一个方法是对数据分组后使用apply和一个在每个数据块上都调用fillna的函数。下面是一些将美国分为东部地区和西部地区的样本数据:

将一些值设置为缺失值:

求东西部均值:

使用分组的平均值来填充NA值:

在另一种情况下,你可能已经在代码中为每个分组预定义了填充值。由于每个分组都有一个内置的name属性,我们可以这样使用:

10.3.4 示例:随机采样与排列

假设想从大数据集中抽取随机样本(有或没有替换)以用于蒙特卡罗模拟目的或某些其他应用程序。有很多方法来执行“抽取”,这里我们使用Series的sample方法。

为了演示,这里我们讲解一种构造一副英式扑克牌的方法:

因此现在我们拥有了一个长度为52的Series, Series的索引包含了牌名,Series的值可以用于Blackjack和其他游戏(为了保持简单,我让’A’为1 ):

现在,基于我之前说的,从这副牌中拿出五张牌可以写成:

假设你想要从每个花色中随机抽取两张牌。由于花色是牌名的最后两个字符,我们可以基于这点进行分组,并使用apply:

或者:

10.3.5 示例:分组加权平均和相关性

在groupby的拆分-应用-联合的范式下,DataFrame的列间操作或两个Seriese之间的操作,例如分组加权平均是可以做到的。作为一个例子,我们使用一个包含分组键和权重值的数据集:

通过category进行分组加权平均如下:

考虑一个从雅虎财经上获得的数据集,该数据集包含一些标普500 (SPX符号)和股票的收盘价:

一个有趣的任务可能是计算一个DataFrame,它包含标普指数(SPX)每日收益的年度相关性(通过百分比变化计算)。作为实现的一种方式,我们首先创建一个计算每列与’SPX’列成对关联的函数:

spx_corr = lambda x:x.corrwith(x['SPX'])

使用pct_change计算close-px百分比的变化:

rets = close_px.pct_change().dropna()

按年对百分比变化进行分组,可以使用单行函数从每个行标签中提取每个datetime标签的year属性:

可以计算内部列相关性。这里我们计算了苹果和微软的年度相关性:

10.3.6 示例:逐组线性回归

在与前一个示例相同的主题中,只要该函数返回一个pandas对象或标量值,就可以使用groupby执行更复杂的按分组统计分析。

可以定义以下regress(回归)函数(使用statsmodels计量经济学库),该函数对每个数据块执行普通最小二乘(OLS)回归:

要计算AAPL在SPX回报上的年度线性回归,执行以下代码:

10.4 数据透视表与交叉表

数据透视表是电子表格程序和其他数据分析软件中常见的数据汇总工具。

它根据一个或多个键聚合一张表的数据,将数据在矩形格式中排列,其中一些分组键是沿着行的,另一些是沿着列的。

Python中的pandas透视表是通过本章所介绍的groupby工具以及使用分层索引的重塑操作实现的。

DataFrame拥有一个pivot_table方法,并且还有还一个顶层的pandas.pivot_table函数。除了为groupby提供一个方便接口,pivot_table还可以添加部分总计,也称作边距。

回到小费数据集,假设你想要计算一张在行方向上按day和smoker排列的分组平均值(默认的pivot_table聚合类型)的表:

这个功能也可以直接使用groupby实现。现在,假设我们只想在tip_pct和size上进行聚合,并根据time分组。将把smoker放入表的列,而将day放入表的行:

我们可以通过传递margins=True来扩充这个表来包含部分总计。

这会添加All行和列标签,其中相应的值是单层中所有数据的分组统计值:

这里,All的值是均值,且该均值是不考虑吸烟者与非吸烟者(All列)或行分组中任何两级的(All行)。

要使用不同的聚合函数时,将函数传递给aggfunc。

例如,'count’或者len将给出一张分组大小的交叉表(计数或出现频率):

如果某些情况下产生了空值(或者NA),你可能想要传递一个fill_value:

10.4.1 交叉表:crosstab

交叉表(简写为crosstab)是数据透视表的一个特殊情况,计算的是分组中的频率。

示例:

作为研究分析的一部分,我们可能想按照国籍和惯用性来总结这些数据。

你可以使用pivot_table来实现这个功能,但是pandas.crosstable函数更为方便:

crosstab的前两个参数可是数组、Series或数组的列表。在小费数据中可以这么做:

参考书籍

        --《利用Python实现数据分析》

数据聚合与分组操作(数据分析)相关推荐

  1. 利用python进行数据分析——使用groupby机制对pandas对象类的数据进行聚合与分组操作

    文章目录 数据聚合与分组操作 一.GroupBy机制 1.1遍历各分组 1.2选取一列或所有列的子集 1.3 通过字典或Series进行分组 1.4 通过函数进行分组 1.5根据索引层级分组 二. 数 ...

  2. pandas数据聚合与分组

    前言 数据聚合于分组操作在众多的关系型或非关系型库中都有涉及,大体原理都是类似,根据某个或者多个业务字段将获取到的数据进行聚合操作或者分组操作,pandas提供了非常友好的分组聚合功能,可以方便使用人 ...

  3. 类的应用python平均分_【数据科学系统学习】Python # 数据分析基本操作[四] 数据规整化和数据聚合与分组运算...

    本篇内容为整理<利用Python进行数据分析>,博主使用代码为 Python3,部分内容和书本有出入. 在前几篇中我们介绍了 NumPy.pandas.matplotlib 三个库的基本操 ...

  4. 【Python】GroupBy:数据聚合与分组运算

    [博客地址]:https://blog.csdn.net/sunyaowu315 [博客大纲地址]:https://blog.csdn.net/sunyaowu315/article/details/ ...

  5. python 数据聚合与分组

    python 数据聚合与分组 前面讲完了字符处理,但对数据进行整体性的聚合运算以及分组操作也是数据分析的重要内容. 通过数据的聚合与分组,我们能更容易的发现隐藏在数据中的规律. 数据分组 数据的分组核 ...

  6. pandas合并groupby_pandas数据聚合与分组运算——groupby方法

    简介 pandas中一类非常重要的操作是数据聚合与分组运算.通过groupby方法能够实现对数据集的拆分.统计.转换等操作,这个过程一气呵成. 在本文中,你将学到: 选取特定列分组: 对分组进行迭代: ...

  7. Python数据聚合和分组运算(1)-GroupBy Mechanics

    前言 Python的pandas包提供的数据聚合与分组运算功能很强大,也很灵活.<Python for Data Analysis>这本书第9章详细的介绍了这方面的用法,但是有些细节不常用 ...

  8. 【学习】数据聚合和分组运算【groupby】

    [学习]数据聚合和分组运算[groupby] 分组键可以有多种方式,且类型不必相同 列表或数组, 某长度与待分组的轴一样 表示DataFrame某个列名的值 字典或Series,给出待分组轴上的值与分 ...

  9. 【学习经典】python 数据聚合与分组运算(part 2)

    本文的前半部分:python 数据聚合与分组运算(part 1) 4. 透视表和交叉表 透视表(pivot table)是各种电子表格程序和其他数据分析软件中一种常见的数据汇总工具.它根据一个或多个键 ...

  10. golang数据聚合的优雅操作

    golang数据聚合的优雅操作 场景: 需要将上传的数据进行特性分组之后再进行数据库批量插入或流向下一个处理方法. 痛点: 由于数据不确定性做聚合操作之后会有多组数据需要缓存,如果多协程进行操作需要将 ...

最新文章

  1. SQL 全角半角转换-(摘抄)
  2. 展望2018:WebRTC大规模商用元年
  3. 智能车联,一场「以人为核心」的智能化变革
  4. 深度窥探 QuickTest 视图(1)
  5. Spring IOC 容器源码分析系列文章导读 1
  6. 随机地址生成器_随机连接神经网络性能超过人工设计!何恺明等人发布新研究...
  7. 让Windows XP系统快上几倍的三个绝招
  8. JVM—类加载器和双亲委派模型
  9. 13001.udp广播接收程序(python)
  10. [Mac]macOS Mojave 10.14.3安装Java
  11. 日语动词变形整理 By Killua
  12. u盘无响应+开启什么服务器,服务没有及时响应启动或控制请求怎么办?如何解决系统服务没有及时响应启动...
  13. ArcGIS DEM数字高程模型数据的生成
  14. 项目专题 1: 结构化方法学自动取款机系统(ATM)分析
  15. DDD领域驱动设计为什么那么玄学,因为你从来都没看过原书
  16. win 下光盘刻录方式
  17. web课程设计网页规划与设计:文化网站设计——中国水墨风书画艺术网站(12个页面)
  18. Navicat Premium 12.0.18 / 12.0.24安装与激活
  19. 黑群晖二合一安装不了套件_【新品推介】3D打印支架袖珍天分仪 | 便携式垂直HF和2米天线套件很亮骚...
  20. 谷歌浏览器关闭跨域限制,允许跨域请求,设置允许访问本地文件

热门文章

  1. java给word表格追加行_Java 使用Spire.Cloud.Word给Word文档添加表格
  2. PCB安规设计是怎样的?怎样设计高压电源的安规?ECM设计间距是怎样的,CAF设计间距要求是怎样的?电源的PCB间距设计指南,安规标准有哪些?380V电源安规设计
  3. mysql堆溢出_MySQL错误1436:线程堆栈溢出,带有简单查询
  4. 几种欧姆龙PLC型号的辨识
  5. CUDA学习笔记(三)——共享内存
  6. linux bt下载没速度慢,linux bt速度之王
  7. Android数据传输加密(三):RSA加密
  8. PS打不开webp格式图片的解决方法
  9. 推荐系统给电影评分排名的方法
  10. mysql 复制表结构或创建新表