简介

pandas中一类非常重要的操作是数据聚合与分组运算。通过groupby方法能够实现对数据集的拆分、统计、转换等操作,这个过程一气呵成。

在本文中,你将学到:

选取特定列分组;

对分组进行迭代;

通过字典或Series分组;

通过函数分组;

通过索引级别分组。

Groupby技术

一个完整的分组运算过程是:“split-apply-combine”(拆分-应用-合并)。首先将数据分组拆分,按照组别划分。这种分组可以针对行(axis=0)或列(axis=1);然后针对分好的组别应用操作函数(聚合、统计等);最后这些结果会合并到最终对象中。这个过程如下:

接下来我们一一介绍。

选取特定列分组

直接来看一个例子:

>>>import numpy as np

>>>import pandas as pd

>>>df = pd.DataFrame({'x': list('aabba'), 'y': ['one', 'two', 'one', 'two', 'one'], 'd1': np.random.randn(5), 'd2': np.random.randn(5)})

x y d1 d2

0 a one 0.053183 0.447796

1 a two -1.117457 -1.476354

2 b one -1.360028 -2.527450

3 b two 1.856344 0.432823

4 a one -0.134772 1.628732

1

2

3

4

5

6

7

8

9

10

>>>importnumpyasnp

>>>importpandasaspd

>>>df=pd.DataFrame({'x':list('aabba'),'y':['one','two','one','two','one'],'d1':np.random.randn(5),'d2':np.random.randn(5)})

xyd1d2

0aone0.0531830.447796

1atwo-1.117457-1.476354

2bone-1.360028-2.527450

3btwo1.8563440.432823

4aone-0.1347721.628732

我们有这样一个DataFrame,假设我们想通过

x 进行分组,并计算

d1 列的平均值,有这样两种方式:

# 先选中d1列,然后再按照x分组

>>>a = df['d1'].groupby(df['x'])

>>>a

# 先分组,在选中d1列

>>>a = df.groupby('x')['d1']

1

2

3

4

5

6

7

8

# 先选中d1列,然后再按照x分组

>>>a=df['d1'].groupby(df['x'])

>>>a

# 先分组,在选中d1列

>>>a=df.groupby('x')['d1']

可以看出这里的变量

a 是一个

GroupBy 对象,可以认为它是做好了分组的中间数据。接下来我们就可以通过

mean() 方法计算平均值:

>>>a.mean()

x

a -0.399682

b 0.248158

Name: d1, dtype: float64

1

2

3

4

5

>>>a.mean()

x

a-0.399682

b0.248158

Name:d1,dtype:float64

结果表明,通过

x 分组后有

'a','b' 两组,最后得到两组的平均值。以上是通过一列进行分组,我们还可以指定多列分组:

>>>b = df.groupby(['x', 'y']).mean()

>>>b

d1 d2

x y

a one -0.040794 1.038264

two -1.117457 -1.476354

b one -1.360028 -2.527450

two 1.856344 0.432823

1

2

3

4

5

6

7

8

>>>b=df.groupby(['x','y']).mean()

>>>b

d1d2

xy

aone-0.0407941.038264

two-1.117457-1.476354

bone-1.360028-2.527450

two1.8563440.432823

在上面的例子中,我们使用的分组都是基于已经有的列名。事实上,我们也可以根据自定义的数组来分组,假如我有如下两个数组:

>>>name = np.array(['joe', 'lucy', 'lucy', 'joe', 'joe'])

>>>year = np.array([2018, 2018, 2019, 2018, 2019])

1

2

>>>name=np.array(['joe','lucy','lucy','joe','joe'])

>>>year=np.array([2018,2018,2019,2018,2019])

根据数组分组:

>>>df['d1'].groupby([name, year]).mean()

joe 2018 0.954764

2019 -0.134772

lucy 2018 -1.117457

2019 -1.360028

Name: d1, dtype: float64

1

2

3

4

5

6

>>>df['d1'].groupby([name,year]).mean()

joe20180.954764

2019-0.134772

lucy2018-1.117457

2019-1.360028

Name:d1,dtype:float64

GroupBy对象迭代

GroupBy对象也支持迭代,可以产生一个二元元组(由分组索引和数据集组成)。比如:

>>>for k, j in a:

print(k)

print(j)

a

0 0.053183

1 -1.117457

4 -0.134772

Name: d1, dtype: float64

b

2 -1.360028

3 1.856344

Name: d1, dtype: float64

1

2

3

4

5

6

7

8

9

10

11

12

13

>>>fork,jina:

print(k)

print(j)

a

00.053183

1-1.117457

4-0.134772

Name:d1,dtype:float64

b

2-1.360028

31.856344

Name:d1,dtype:float64

如果是多个分组索引,二元元组的第一个元素就是分组索引组成的元组:

>>>for (k1, k2), j in df.groupby(['x', 'y']):

print(k1, k2)

print(j)

a one

x y d1 d2

0 a one 0.053183 0.447796

4 a one -0.134772 1.628732

a two

x y d1 d2

1 a two -1.117457 -1.476354

b one

x y d1 d2

2 b one -1.360028 -2.52745

b two

x y d1 d2

3 b two 1.856344 0.432823

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

>>>for(k1,k2),jindf.groupby(['x','y']):

print(k1,k2)

print(j)

aone

xyd1d2

0aone0.0531830.447796

4aone-0.1347721.628732

atwo

xyd1d2

1atwo-1.117457-1.476354

bone

xyd1d2

2bone-1.360028-2.52745

btwo

xyd1d2

3btwo1.8563440.432823

既然知道groupby对象是一个二元元组,一个可能有用的操作技巧是将它转变成字典,然后就可以通过键访问对应的数据:

>>>c = dict(list(df.groupby(['x', 'y'])))

>>>c[('a', 'one')]

x y d1 d2

0 a one 0.053183 0.447796

4 a one -0.134772 1.628732

1

2

3

4

5

>>>c=dict(list(df.groupby(['x','y'])))

>>>c[('a','one')]

xyd1d2

0aone0.0531830.447796

4aone-0.1347721.628732

除了在行上进行分组,我们也可以在列上进行分组:

>>>df.dtypes

x object

y object

d1 float64

d2 float64

dtype: object

1

2

3

4

5

6

>>>df.dtypes

xobject

yobject

d1float64

d2float64

dtype:object

通过

dtypes 能够获取每列的数据类型,接着我们根据数据类型对列进行分组:

>>>d = df.groupby(df.dtypes, axis=1)

>>>for k, j in d:

print(k)

print(j)

float64

d1 d2

0 0.053183 0.447796

1 -1.117457 -1.476354

2 -1.360028 -2.527450

3 1.856344 0.432823

4 -0.134772 1.628732

object

x y

0 a one

1 a two

2 b one

3 b two

4 a one

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

>>>d=df.groupby(df.dtypes,axis=1)

>>>fork,jind:

print(k)

print(j)

float64

d1d2

00.0531830.447796

1-1.117457-1.476354

2-1.360028-2.527450

31.8563440.432823

4-0.1347721.628732

object

xy

0aone

1atwo

2bone

3btwo

4aone

通过字典或Series分组

在前面就讲到可以根据自定义的数组进行分组,那么我们也可以传入一个字典或者Series映射现有的行或列,再通过自定义的数组

>>>df1 = pd.DataFrame(np.random.randn(4, 4), columns=['aa', 'bb', 'cc', 'dd'], index=list('abcd'))

>>>df1

aa bb cc dd

a -0.684296 -1.282066 0.582461 0.010453

b 1.160331 1.089198 -0.525495 0.613127

c 0.605130 1.214561 1.843957 -1.464937

d 0.997813 0.049371 -0.319833 -0.396488

1

2

3

4

5

6

7

>>>df1=pd.DataFrame(np.random.randn(4,4),columns=['aa','bb','cc','dd'],index=list('abcd'))

>>>df1

aabbccdd

a-0.684296-1.2820660.5824610.010453

b1.1603311.089198-0.5254950.613127

c0.6051301.2145611.843957-1.464937

d0.9978130.049371-0.319833-0.396488

建立一个字典映射:

>>>dict1 = {'a': 'joe', 'b': 'joe', 'c': 'lucy', 'd': 'joe', 'e': 'lucy'}

>>>df1.groupby(dict1).mean()

aa bb cc dd

joe 0.491283 -0.047832 -0.087622 0.075697

lucy 0.605130 1.214561 1.843957 -1.464937

1

2

3

4

5

>>>dict1={'a':'joe','b':'joe','c':'lucy','d':'joe','e':'lucy'}

>>>df1.groupby(dict1).mean()

aabbccdd

joe0.491283-0.047832-0.0876220.075697

lucy0.6051301.2145611.843957-1.464937

将现有的行索引按照

['joe','lucy'] 来分组。

或者使用Series:

>>>dict1_series = pd.Series(dict1)

>>>dict1_series

a joe

b joe

c lucy

d joe

e lucy

dtype: object

>>>df1.groupby(dict1_series).mean()

aa bb cc dd

joe 0.491283 -0.047832 -0.087622 0.075697

lucy 0.605130 1.214561 1.843957 -1.464937

1

2

3

4

5

6

7

8

9

10

11

12

13

>>>dict1_series=pd.Series(dict1)

>>>dict1_series

ajoe

bjoe

clucy

djoe

elucy

dtype:object

>>>df1.groupby(dict1_series).mean()

aabbccdd

joe0.491283-0.047832-0.0876220.075697

lucy0.6051301.2145611.843957-1.464937

通过函数进行分组

假设有这样地数据:

>>>df2 = df1.rename(index={'b':'bb', 'd':'dd'})

>>>df2

aa bb cc dd

a -0.684296 -1.282066 0.582461 0.010453

bb 1.160331 1.089198 -0.525495 0.613127

c 0.605130 1.214561 1.843957 -1.464937

dd 0.997813 0.049371 -0.319833 -0.396488

1

2

3

4

5

6

7

>>>df2=df1.rename(index={'b':'bb','d':'dd'})

>>>df2

aabbccdd

a-0.684296-1.2820660.5824610.010453

bb1.1603311.089198-0.5254950.613127

c0.6051301.2145611.843957-1.464937

dd0.9978130.049371-0.319833-0.396488

我们想根据行索引字符串的长度进行分组,就可以直接调用

len 函数:

>>>df2.groupby(len).sum()

aa bb cc dd

1 -0.079166 -0.067505 2.426418 -1.454484

2 2.158144 1.138569 -0.845328 0.216639

1

2

3

4

>>>df2.groupby(len).sum()

aabbccdd

1-0.079166-0.0675052.426418-1.454484

22.1581441.138569-0.8453280.216639

行索引1、2就表示行索引字符串长度为1和2的两个组。

我们还可以将函数和数组、列表、字典、Series混合使用:

>>>list1 = [2018, 2018, 2019, 2019]

>>>df2.groupby([len, list1]).max()

aa bb cc dd

1 2018 -0.684296 -1.282066 0.582461 0.010453

2019 0.605130 1.214561 1.843957 -1.464937

2 2018 1.160331 1.089198 -0.525495 0.613127

2019 0.997813 0.049371 -0.319833 -0.396488

1

2

3

4

5

6

7

8

>>>list1=[2018,2018,2019,2019]

>>>df2.groupby([len,list1]).max()

aabbccdd

12018-0.684296-1.2820660.5824610.010453

20190.6051301.2145611.843957-1.464937

220181.1603311.089198-0.5254950.613127

20190.9978130.049371-0.319833-0.396488

通过索引级别分组

对于层次化索引分组,可以根据

level 参数选择索引级别进行分组。如果有下面这个层次化数据集:

>>>columns = pd.MultiIndex.from_arrays([['one', 'one', 'two', 'two'], ['a', 'c', 'a', 'b']], names=['key1', 'key2'])

>>>df3 = pd.DataFrame(np.random.randn(3, 4), columns=columns)

>>>df3

key1 one two

key2 a c a b

0 0.379105 -0.467082 -0.196458 0.913196

1 -0.773172 0.058906 -0.733571 0.834142

2 -0.609070 0.916934 0.346457 -0.620837

1

2

3

4

5

6

7

8

>>>columns=pd.MultiIndex.from_arrays([['one','one','two','two'],['a','c','a','b']],names=['key1','key2'])

>>>df3=pd.DataFrame(np.random.randn(3,4),columns=columns)

>>>df3

key1onetwo

key2acab

00.379105-0.467082-0.1964580.913196

1-0.7731720.058906-0.7335710.834142

2-0.6090700.9169340.346457-0.620837

level 参数可以传入级别名称或者编号:

# 传入级别名称

>>>df3.groupby(level='key1', axis=1).mean()

key1 one two

0 -0.043988 0.358369

1 -0.357133 0.050286

2 0.153932 -0.137190

# 传入级别编号

>>>df3.groupby(level=0, axis=1).mean()

key1 one two

0 -0.043988 0.358369

1 -0.357133 0.050286

2 0.153932 -0.137190

1

2

3

4

5

6

7

8

9

10

11

12

13

# 传入级别名称

>>>df3.groupby(level='key1',axis=1).mean()

key1onetwo

0-0.0439880.358369

1-0.3571330.050286

20.153932-0.137190

# 传入级别编号

>>>df3.groupby(level=0,axis=1).mean()

key1onetwo

0-0.0439880.358369

1-0.3571330.050286

20.153932-0.137190

设置了

axis=1 ,表示在列上进行分组从外到内的级别编号依次0、1…

总结

再本文中初步介绍了groupby方法的使用,可以根据不同的方式(字典、Series、数组、函数、索引级别)选择分组索引进行分组。在后面的文章中我们还会详细介绍传入函数的应用,因为这在实际工作中使用较多。

pandas合并groupby_pandas数据聚合与分组运算——groupby方法相关推荐

  1. pandas 根据列名索引多列数据_Pandas 数据聚合与分组运算[groupby+apply]速查笔记

    利用Pandas将数据进行分组,并将各组进行聚合或自定义函数处理. Pandas中Groupby分组与聚合过程 导入模块 import pandas as pd 缩写 df表示Dataframe对象 ...

  2. 数据聚合与分组运算——GroupBy

    2019独角兽企业重金招聘Python工程师标准>>> pandas提供了一个灵活高效的groupby功能,它使你能以一种自然的方式对数据集进行切片.切块.摘要等操作. 根据一个或多 ...

  3. Python之数据聚合与分组运算

    Python之数据聚合与分组运算 1. 关系型数据库方便对数据进行连接.过滤.转换和聚合. 2. Hadley Wickham创建了用于表示分组运算术语"split-apply-combin ...

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

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

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

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

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

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

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

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

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

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

  9. vfp python_python foxpro数据聚合和分组运算——分组级运算和转换(3)

    数据聚合和分组运算--分组级运算和转换(3),有需要的朋友可以参考下. 1.假设我们想要为一个DataFrame添加一个用于存放各索引分组平均值的列,一个办法是先聚合再合并: >>> ...

最新文章

  1. linux suse10虚拟机在静态IP局域网中如何设置桥接上网
  2. Mac和 iOS 下的对称和非对称加密算法的使用
  3. Elasticsearch的智能判断:动态添加数据映射
  4. win7+计算机+桌面图标不见了怎么办,win7电脑系统桌面图标不见了怎么办
  5. linux内核 快速分片,linux内核学习笔记------ip报文的分片
  6. MatchingFrontier包简介及R实现
  7. 【完美解决】ds1302外置时钟模块重复初始化时间问题(单片机掉电,模块电池供电)
  8. 2022最新小额借贷系统程序源码+附教程文档
  9. excel导入的数据中文字段转英文
  10. OpenXML标签含义
  11. level set method 水平集方法基本问题
  12. 如何手机桌面加计算机,教你自制手机、电脑壁纸|手机一键加字、加光晕特效,4步搞定!...
  13. 【数据库】--- Redis
  14. STM32F429_DWM物联网开发板
  15. 基于ICP算法的三维点云数据拼接算法的实现
  16. ElasticSearchTransportClient集成SearchGuard插件实现索引级别的权限管控
  17. 计算机配置好坏怎么看,怎么看电脑配置,电脑配置好坏信息一目了然-腾讯电脑管家...
  18. 3D点云处理:数据集生成点云
  19. 四叉树算法:iOS地图点标记聚合方案
  20. WhatsApp翻译 边聊边译 实时自动翻译

热门文章

  1. linux分区安装win7,安装linuxmint与win7双系统的经验
  2. 解决@Autowired警告
  3. layui制作二维码
  4. Cesium常用事件,包括点击事件,鼠标事件,相机移动事件
  5. 2020年复旦大学计算机学院夏令营经历
  6. 2020高考倒计时html,最新2020高考倒计时祝福语
  7. NetworkX学习及使用
  8. Nginx配置静态访问txt文件(微信校验文件)
  9. Java 判断平衡二叉树
  10. 商品期货CTA策略系列文章 -- CTA策略的起源