Pandas数据分析——超好用的Groupby详解

微信公众号:「Python读财」
如有问题或建议,请公众号留言

在日常的数据分析中,经常需要将数据根据某个(多个)字段划分为不同的群体(group)进行分析,如电商领域将全国的总销售额根据省份进行划分,分析各省销售额的变化情况,社交领域将用户根据画像(性别、年龄)进行细分,研究用户的使用情况和偏好等。在Pandas中,上述的数据处理操作主要运用groupby完成,这篇文章就介绍一下groupby的基本原理及对应的aggtransformapply操作。

为了后续图解的方便,采用模拟生成的10个样本数据,代码和数据如下:

company=["A","B","C"]

data=pd.DataFrame({
    "company":[company[x] for x in np.random.randint(0,len(company),10)],
    "salary":np.random.randint(5,50,10),
    "age":np.random.randint(15,50,10)
}
)
company salary age
0 C 43 35
1 C 17 25
2 C 8 30
3 A 20 22
4 B 10 17
5 B 21 40
6 A 23 33
7 C 49 19
8 B 8 30

一、Groupby的基本原理

在pandas中,实现分组操作的代码很简单,仅需一行代码,在这里,将上面的数据集按照company字段进行划分:

In [5]: group = data.groupby("company")

将上述代码输入ipython后,会得到一个DataFrameGroupBy对象

In [6]: group
Out[6]: <pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002B7E2650240>

那这个生成的DataFrameGroupBy是啥呢?对data进行了groupby后发生了什么?ipython所返回的结果是其内存地址,并不利于直观地理解,为了看看group内部究竟是什么,这里把group转换成list的形式来看一看:

In [8]: list(group)
Out[8]:
[('A',   company  salary  age
  3       A      20   22
  6       A      23   33), 
 ('B',   company  salary  age
  4       B      10   17
  5       B      21   40
  8       B       8   30), 
 ('C',   company  salary  age
  0       C      43   35
  1       C      17   25
  2       C       8   30
  7       C      49   19)]

转换成列表的形式后,可以看到,列表由三个元组组成,每个元组中,第一个元素是组别(这里是按照company进行分组,所以最后分为了A,B,C),第二个元素的是对应组别下的DataFrame,整个过程可以图解如下:

groupby原理.png

总结来说,groupby的过程就是将原有的DataFrame按照groupby的字段(这里是company),划分为若干个分组DataFrame,被分为多少个组就有多少个分组DataFrame所以说,在groupby之后的一系列操作(如aggapply等),均是基于子DataFrame的操作。理解了这点,也就基本摸清了Pandas中groupby操作的主要原理。下面来讲讲groupby之后的常见操作。

二、agg 聚合操作

聚合操作是groupby后非常常见的操作,会写SQL的朋友对此应该是非常熟悉了。聚合操作可以用来求和、均值、最大值、最小值等,下面的表格列出了Pandas中常见的聚合操作。

函数 用途
min 最小值
max 最大值
sum 求和
mean 均值
median 中位数
std 标准差
var 方差
count 计数

针对样例数据集,如果我想求不同公司员工的平均年龄和平均薪水,可以按照下方的代码进行:

In [12]: data.groupby("company").agg('mean')
Out[12]:
         salary    age
company
A         21.50  27.50
B         13.00  29.00
C         29.25  27.25

如果想对针对不同的列求不同的值,比如要计算不同公司员工的平均年龄以及薪水的中位数,可以利用字典进行聚合操作的指定:

In [17]: data.groupby('company').agg({'salary':'median','age':'mean'})
Out[17]:
         salary    age
company
A          21.5  27.50
B          10.0  29.00
C          30.0  27.25

agg聚合过程可以图解如下(第二个例子为例):

agg图解.png

三、transform

transform是一种什么数据操作?和agg有什么区别呢?为了更好地理解transformagg的不同,下面从实际的应用场景出发进行对比。

在上面的agg中,我们学会了如何求不同公司员工的平均薪水,如果现在需要在原数据集中新增一列avg_salary,代表员工所在的公司的平均薪水(相同公司的员工具有一样的平均薪水),该怎么实现呢?如果按照正常的步骤来计算,需要先求得不同公司的平均薪水,然后按照员工和公司的对应关系填充到对应的位置,不用transform的话,实现代码如下:

In [21]: avg_salary_dict = data.groupby('company')['salary'].mean().to_dict()

In [22]: data['avg_salary'] = data['company'].map(avg_salary_dict)

In [23]: data
Out[23]:
  company  salary  age  avg_salary
0       C      43   35       29.25
1       C      17   25       29.25
2       C       8   30       29.25
3       A      20   22       21.50
4       B      10   17       13.00
5       B      21   40       13.00
6       A      23   33       21.50
7       C      49   19       29.25
8       B       8   30       13.00

如果使用transform的话,仅需要一行代码:

In [24]: data['avg_salary'] = data.groupby('company')['salary'].transform('mean')

In [25]: data
Out[25]:
  company  salary  age  avg_salary
0       C      43   35       29.25
1       C      17   25       29.25
2       C       8   30       29.25
3       A      20   22       21.50
4       B      10   17       13.00
5       B      21   40       13.00
6       A      23   33       21.50
7       C      49   19       29.25
8       B       8   30       13.00

还是以图解的方式来看看进行groupbytransform的实现过程(为了更直观展示,图中加入了company列,实际按照上面的代码只有salary列):

transform图解.png

图中的大方框是transformagg所不一样的地方,对agg而言,会计算得到ABC公司对应的均值并直接返回,但对transform而言,则会对每一条数据求得相应的结果,同一组内的样本会有相同的值,组内求完均值后会按照原索引的顺序返回结果,如果有不理解的可以拿这张图和agg那张对比一下。

四、apply

apply应该是大家的老朋友了,它相比aggtransform而言更加灵活,能够传入任意自定义的函数,实现复杂的数据操作。在Pandas数据处理三板斧——map、apply、applymap详解
)中,介绍了apply的使用,那在groupby后使用apply和之前所介绍的有什么区别呢?

区别是有的,但是整个实现原理是基本一致的。两者的区别在于,对于groupby后的apply,以分组后的子DataFrame作为参数传入指定函数的,基本操作单位是DataFrame,而之前介绍的apply的基本操作单位是Series。还是以一个案例来介绍groupby后的apply用法。

假设我现在需要获取各个公司年龄最大的员工的数据,该怎么实现呢?可以用以下代码实现:

In [38]: def get_oldest_staff(x):
    ...:     df = x.sort_values(by = 'age',ascending=True)
    ...:     return df.iloc[-1,:]
    ...:

In [39]: oldest_staff = data.groupby('company',as_index=False).apply(get_oldest_staff)

In [40]: oldest_staff
Out[40]:
  company  salary  age  
0       A      23   33       
1       B      21   40       
2       C      43   35      

这样便得到了每个公司年龄最大的员工的数据,整个流程图解如下:

apply过程.png

可以看到,此处的apply和上篇文章中所介绍的作用原理基本一致,只是传入函数的参数由Series变为了此处的分组DataFrame

最后,关于apply的使用,这里有个小建议,虽然说apply拥有更大的灵活性,但apply的运行效率会比aggtransform更慢。所以,groupby之后能用aggtransform解决的问题还是优先使用这两个方法,实在解决不了了才考虑使用apply进行操作。

扫码关注公众号「Python读财」,第一时间获取干货,还可以加Python学习交流群!!
公众号二维码.jpg

Image placeholder
zhouqi
未设置
  65人点赞

没有讨论,发表一下自己的看法吧

推荐文章
Python数据分析实战 | 爬遍拉勾网,带你看看数据分析师还吃香吗?

微信公众号:「Python读财」如有问题或建议,请公众号留言伴随着移动互联网的飞速发展,越来越多用户被互联网连接在一起,用户所积累下来的数据越来越多,市场对数据方面人才的需求也越来越大,由此也带火了如

Pandas数据处理三板斧——map、apply、applymap详解

微信公众号:「Python读财」如有问题或建议,请公众号留言在日常的数据处理中,经常会对一个DataFrame进行逐行、逐列和逐元素的操作,对应这些操作,Pandas中的map、apply和apply

10个超好用的配色网站

01MaterialPalette网站地址:http://www.materialpalette.com/MaterialPalette是一款提供MaterialDesign配色的线上工具,它的用法很

数据结构与算法分析——开篇以及复杂度分析

开篇 你也许已经发现了,工作了几年,原以为已经是一只老鸟。但看到刚参加工作的同事,你发现,原来自己一直在原地踏步。跟新人相比,你的唯一优势就是对业务更熟悉而已,别的就没有什么优势了。 怎样才能够让自己

数据结构与算法分析——开篇以及复杂度分析

开篇你也许已经发现了,工作了几年,原以为已经是一只老鸟。但看到刚参加工作的同事,你发现,原来自己一直在原地踏步。跟新人相比,你的唯一优势就是对业务更熟悉而已,别的就没有什么优势了。怎样才能够让自己更上

数据分析利器之Pandas

Pandas是一个python的开源库,它基于Numpy,提供了多种高性能且易于使用的数据结构。Pandas最初被用作金融数据分析工具而开发,由于它有着强大的功能,目前广泛应用于数据分析、机器学习以及

数据结构与算法分析——链表

链表链表是一种常见的数据结构,是一组有序的数据,每个链表中的数据项称为元素。它跟数组很像,二者对比学习会更容易理解和记忆。数组是内存中连续的一块,不会间断。链表在内存中不一定是连续的一块。如果内存只剩

数据结构与算法分析——队列

定义队列,和栈类似,也是一种操作受限的线性表数据结构。与栈结构不同的是,可以对队列2端操作,要求数据从一端进(入队),从另一端出(出队)。队列遵循"先进先出"的原则,即最先进队列的数据元素,同样要最先

数据结构与算法分析——栈

定义栈是一种操作受限的线性表,只支持在一端进行插入和删除操作(入栈和出栈)。后进先出、先进后出是它最大的特点。当某个数据集合只在一端插入和删除数据,并满足先进后出的特性时,就可以选择栈这种数据结构。实

我们为什么应该关注SaaS数据备份?

使用基于云的应用程序,也称为软件即服务(SaaS),如Office365和Salesforce,现在几乎已成为大多数组织运营的主流部分。依赖这些服务承载您业务的关键部分意味着它们的可用性对确保您的业务

redis数据结构(二) - 字符串

基于redis5.0的版本。字符串编码:字符串对象的编码可以是int,raw或者embstr。1.rawraw就是redisObject+sds,即redisObject的ptr指针指向一个sds对象

清晰架构(Clean Architecture)的Go微服务: 日志管理

良好的日志记录可以提供丰富的日志数据,便于在调试时发现问题,从而大大提高编码效率。记录器提供的自动化信息越多越好,日志信息也需要以简洁的方式呈现,便于找到重要的数据。日志需求: 无需修改业务代码即可切

AB test | 数据分析师面试必知 !

前言关于ABtest的重要性无需多言,数据、产品等从业人员几乎必知,好的数据科学家我想一定是知道理解业务比模型更为重要,而ABtest就是伴随着业务增长的利器。如果你心中的ABtest几乎都没有用到中

基于 Spark 的数据分析实践

转载本文需注明出处:微信公众号EAWorld,违者必究。引言:Spark是在借鉴了MapReduce之上发展而来的,继承了其分布式并行计算的优点并改进了MapReduce明显的缺陷。Spark主要包含

如何避免人类偏见对数据分析产生影响

随着越来越多的企业开始采用机器学习技术以实现流程的自动化,人们也逐渐开始质疑计算机决策中的伦理含义。我们如何处理计算机系统中潜在的偏见?相对较少被提及但同样重要的,是人类本身的偏见,它与分析和商业决策

实现人工智能落地 你还差一个“数据分析流水线”的距离

在智慧生产场景,生产制造商可以在生产线上利用深度学习,尤其是图像识别,将产品的质量检测自动化。比如自动检测产品表面有没有划伤、有没有零部件的缺失、有没有标签的错位。研究表明,相比人工检测,智慧检测可以

调查:2019年数据分析市场面临的挑战有哪些?

分析和数据科学行业对人才的需求急剧增长,为该行业求职者提供了很多工作机会。无论是500强还是初创企业,每个团队都在使用分析来从数据中获得有价值的信息。然而,在人才、客户定位和收集数据等方面,这个行业仍

零基础的小白怎么学习数据分析?

微信公众号:「Python读财」如有问题或建议,请公众号留言作为一个从超级菜鸟阶段过来的人,也曾迷茫,也曾面对一大堆资料不知所措,从无到有踩过太多的坑,在这里分享一下我总结出来的数据分析学习路径,为了

最适合入门的Python数据分析实战项目

微信公众号:「Python读财」如有问题或建议,请公众号留言伴随着移动互联网的飞速发展,越来越多用户被互联网连接在一起,用户所积累下来的数据越来越多,市场对数据方面人才的需求也越来越大,由此也带火了如

基于性能的路由(PBR)——SD-WAN的热点话题

边界网关协议(BGP)被认为是互联网的粘合剂。然而,如果我们从长远的角度来看,还有一个问题仍未得到解答。BGP是否有能力选择最佳路径而不是最短路径?有些供应商为基于BGP的网络提供基于性能的解决方案。

Go语言高级编程_4.7 pbgo: 基于Protobuf的框架

4.7pbgo:基于Protobuf的框架 pbgo是我们专门针对本节内容设计的较为完整的迷你框架,它基于Protobuf的扩展语法,通过插件自动生成rpc和rest相关代码。在本章第二节我们已经展示

PB级数据实时查询,滴滴Elasticsearch多集群架构实践

Elasticsearch是基于Lucene实现的分布式搜索引擎,提供了海量数据实时检索和分析能力。Elastic 公司开源的一系列产品组成的ElasticStack,可以为日志服务、搜索引擎、系统监

7 个好用的 TypeScript 新功能

作者:RC翻译:疯狂的技术宅 原文:https://blog.bitsrc.io/7-new-... 未经允许严禁转载 TypeScript语言小组一直在以惊人的速度推出新功能。从最新的《Javasc

海量数据AtlasDB:把“数据库好用”这件事做到极致

导语:坚守初心、不辱使命,近期海量数据研发的企业级数据库AtlasDB获得了市场的普遍关注。这款以“好用”著称的国产数据库产品,不仅承载着海量数据公司对技术创新的坚持和投入,更凝结着一群拥有“工匠之心

Android兼容Java 8语法特性的原理分析

本文主要阐述了Lambda表达式及其底层实现(invokedynamic指令)的原理、Android第三方插件RetroLambda对其的支持过程、Android官方最新的dex编译器D8对其的编译支