分组键可以有多种方式,且类型不必相同

  • 列表或数组, 某长度与待分组的轴一样
  • 表示DataFrame某个列名的值
  • 字典或Series,给出待分组轴上的值与分组名之间的对应关系
  • 函数用于处理轴索引或索引中的各个标签

看一下示例:

import numpy as np
import pandas as pd
df = pd.DataFrame({'key1':['a','a','b','b','a'],
'key2':['one','two','one','two','one'],
'data1':np.random.randn(5),
'data2':np.random.randn(5)})
df
Out[3]:
      data1     data2 key1 key2
0  1.236062 -0.576333    a  one
1 -1.925623 -0.874375    a  two
2  1.472156 -0.005463    b  one
3 -0.155766  2.318643    b  two
4 -1.961012 -0.947843    a  one

按key1分组,并计算data1列的平均值。访问data1,并根据key1调用groupby

#按key1分组,访问data1的平均值
df['data1'].groupby(df['key1']).mean() Out[4]:
key1
a -0.883525
b 0.658195
Name: data1, dtype: float64

数据根据分组键进行了聚合,产生一个新的Series,其索引为key1列中的唯一值

如果一次传入多个数组,就会得到不同的结果

df['data1'].groupby([df['key1'], df['key2']]).mean()
Out[5]:
key1 key2
a one -0.362475
two -1.925623
b one 1.472156
two -0.155766
Name: data1, dtype: float64
#这里,通过两个键进行了分组,得到的Series具有一个层次化索引(由唯一的键对组成)
means.unstack()
Out[7]:
key2       one       two
key1                    
a    -0.362475 -1.925623
b     1.472156 -0.155766

GroupBy的size方法,可以返回一个含有分组大小的Series

df.groupby(['key1', 'key2']).size()
Out[13]:
key1 key2
a one 2
two 1
b one 1
two 1
dtype: int64

注意:分组键中的任何缺失 值都会被排除在结果之外

1、对分组进行迭代

GroupBy对象支持迭代,可以产生一组二元元组(由分组名和数据块组成)

for name, group in df.groupby('key1'):
print(name)
print(group) a
data1 data2 key1 key2
0 1.236062 -0.576333 a one
1 -1.925623 -0.874375 a two
4 -1.961012 -0.947843 a one
b
data1 data2 key1 key2
2 1.472156 -0.005463 b one
3 -0.155766 2.318643 b two

对于多重键的情况,元组的第一个元素将会是由键值组成的元组:

for (k1, k2), group in df.groupby(['key1', 'key2']):
print(k1, k2)
print(group) a one
data1 data2 key1 key2
0 1.236062 -0.576333 a one
4 -1.961012 -0.947843 a one
a two
data1 data2 key1 key2
1 -1.925623 -0.874375 a two
b one
data1 data2 key1 key2
2 1.472156 -0.005463 b one
b two
data1 data2 key1 key2
3 -0.155766 2.318643 b two

你可以对这些数据片段做任何操作,将这些数据片段做成一个字典:

pieces = dict(list(df.groupby('key1')))

pieces
Out[18]:
{'a': data1 data2 key1 key2
0 1.236062 -0.576333 a one
1 -1.925623 -0.874375 a two
4 -1.961012 -0.947843 a one, 'b': data1 data2 key1 key2
2 1.472156 -0.005463 b one
3 -0.155766 2.318643 b two} pieces['b']
Out[19]:
      data1     data2 key1 key2
2  1.472156 -0.005463    b  one
3 -0.155766  2.318643    b  two

groupby默认在axis = 0 上进行分组的,通过设置也可以在其他任何轴上进行分组

df.dtypes
Out[20]:
data1 float64
data2 float64
key1 object
key2 object
dtype: object
grouped = df.groupby(df.dtypes, axis = 1)

dict(list(grouped))
Out[22]:
{dtype('float64'): data1 data2
0 1.236062 -0.576333
1 -1.925623 -0.874375
2 1.472156 -0.005463
3 -0.155766 2.318643
4 -1.961012 -0.947843, dtype('O'): key1 key2
0 a one
1 a two
2 b one
3 b two
4 a one}

2、选取一个或一组列

对于由DataFrame产生的GroupBy对象,如果用一个(单个字符串)或一组(字符串数组)列名对其进行索引,就能实现选取部分列进行聚合的目的。也就是说

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

尤其对于大数据集,很可能只需要对部分列进行聚合

df.groupby(['key1', 'key2'])[['data2']].mean()
Out[25]:
data2
key1 key2
a one -0.762088
two -0.874375
b one -0.005463
two 2.318643

这种索引操作所返回的对象是一个已分组的DataFrame或已分组的Series(如果传入的是标量形式的单个列名)

3、通过字典或Series进行分组

people.ix[2:3, ['b', 'c']] = np.nan #添加几个NA值

people
Out[29]:
a b c d e
joe -0.237225 -0.583231 2.506186 0.764346 2.628579
Steve -0.125559 -0.185558 -0.226190 -1.624512 -0.988784
Wes 0.337773 NaN NaN -2.489380 -0.064929
Jim 1.052081 -0.888873 1.227694 0.809077 1.031245
Travis 0.042581 0.793400 0.316565 -1.098852 0.129532

假设已知列的分组关系,并根据根据分组计算列的总计

#ix再回顾温习一下
mapping = {'a': 'red', 'b': 'red', 'c': 'blue', 'd': 'blue', 'e': 'red', 'f': 'orange'}
#现在只需将这个字典传给groupby即可
by_column = people.groupby(mapping, axis = 1)
by_column.sum() Out[32]:
            blue       red
joe     3.270531  1.808124
Steve  -1.850702 -1.299900
Wes    -2.489380  0.272844
Jim     2.036771  1.194453
Travis -0.782287  0.965513

Series也有同样的功能,被看做一个固定大小的映射,如果是Series作为分组键,则pandas会检查Series以确保其索引跟分组轴是对齐的

map_series = pd.Series(mapping)

map_series
Out[34]:
a red
b red
c blue
d blue
e red
f orange
dtype: object
people.groupby(map_series, axis = 1).count()
Out[35]:
blue red
joe 2 3
Steve 2 3
Wes 1 2
Jim 2 3
Travis 2 3

4、通过函数进行分组

根据人名的长度进行分组,虽然可以求取一个字符串长度数组,但其实仅仅传入len函数就可以

people.groupby(len).sum()
Out[36]:
a b c d e
3 1.152630 -1.472104 3.733879 -0.915957 3.594895
5 -0.125559 -0.185558 -0.226190 -1.624512 -0.988784
6 0.042581 0.793400 0.316565 -1.098852 0.129532

将函数跟数组、列表、字典、Series混合使用,因为任何东西最终都会被转换为数组

people.groupby([len, key_list]).min()  #这个没有理解
Out[38]:
a b c d e
3 one -0.237225 -0.583231 2.506186 -2.489380 -0.064929
two 1.052081 -0.888873 1.227694 0.809077 1.031245
5 one -0.125559 -0.185558 -0.226190 -1.624512 -0.988784
6 two 0.042581 0.793400 0.316565 -1.098852 0.129532

5、根据索引级别分组

层次化索引数据集最方便的地方就在于它能够根据索引级别进行聚合,要实现该目的,通过level关键字传入级别编号或名称即可

columns = pd.MultiIndex.from_arrays([['US', 'US', 'US', 'JP', 'JP'], [1, 3, 5, 1, 3]], names = ['cty', 'tenor'])

hier_df = pd.DataFrame(np.random.randn(4, 5), columns = columns)

hier_df
Out[41]:
cty US JP
tenor 1 3 5 1 3
0 -0.248738 0.627953 2.071784 0.245686 -1.590562
1 1.723024 0.111605 -0.520688 -0.370661 -0.287072
2 0.061884 -0.502882 0.281061 0.083908 2.224092
3 -0.341529 0.945064 -0.785416 -0.443815 0.186289
hier_df.groupby(level = 'cty', axis =1).count()
Out[42]:
cty JP US
0 2 3
1 2 3
2 2 3
3 2 3

二、数据聚合

任何能够从数组产生标量值的数据转换过程。比如mean、 count 、min 以及 sum等。许多常见的聚合运算都有就地计算数据集统计信息的优化实现

quantile可以计算Series或DataFrame列的样本分位数
df
Out[43]:
      data1     data2 key1 key2
0  1.236062 -0.576333    a  one
1 -1.925623 -0.874375    a  two
2  1.472156 -0.005463    b  one
3 -0.155766  2.318643    b  two
4 -1.961012 -0.947843    a  one
grouped = df.groupby('key1')
grouped
grouped['data1'].quantile(0.9)
Out[47]:
key1
a    0.603725
b    1.309364
Name: data1, dtype: float64
#注意:如果传入的百分位上没有值,则quantile会进行线性插值

实际上,GroupBy会高效地对Series进行切片,然后对各片调用piece, quantile(0.9), 最后将这些结果组成成最终结果

使用自己的聚合函数,只需将其传入aggregate或agg方法即可

def peak_to_peak(arr):
return arr.max() - arr.min() grouped.agg(peak_to_peak)
Out[49]:
data1 data2
key1
a 3.197074 0.371510
b 1.627922 2.324107
#describe也可以这样用
grouped.describe()
Out[50]:
data1 data2
key1
a count 3.000000 3.000000
mean -0.883525 -0.799517
std 1.835701 0.196743
min -1.961012 -0.947843
25% -1.943318 -0.911109
50% -1.925623 -0.874375
75% -0.344781 -0.725354
max 1.236062 -0.576333
b count 2.000000 2.000000
mean 0.658195 1.156590
std 1.151114 1.643392
min -0.155766 -0.005463
25% 0.251215 0.575563
50% 0.658195 1.156590
75% 1.065176 1.737617
max 1.472156 2.318643

经过优化的groupby方法

1、面向列的多函数应用

#备注,tips没有下载下来,这里仅作为展示实例
grouped = tips.groupby(['sex', 'smoker'])
grouped_pct = grouped(['tip_pct'])
grouped_pct.agg('mean')
grouped_pct.agg('mean', 'std', peak_to_peak)
#以无索引的形式返回聚合数据
tips.groupby(['sex', 'smoker'], as_index = False).mean()

三、分组级运算和转换

transform和apply方法,它能够执行更多其他的分组运算

为一个DataFrame添加 一个用于存储各索引分组平均值的列,一个办法是先聚合再合并

df
Out[51]:
data1 data2 key1 key2
0 1.236062 -0.576333 a one
1 -1.925623 -0.874375 a two
2 1.472156 -0.005463 b one
3 -0.155766 2.318643 b two
4 -1.961012 -0.947843 a one k1_means = df.groupby('key1').mean().add_prefix('mean_') k1_means
Out[53]:
mean_data1 mean_data2
key1
a -0.883525 -0.799517
b 0.658195 1.156590
pd.merge(df, k1_means, left_on = 'key1', right_index = True)
Out[54]:
data1 data2 key1 key2 mean_data1 mean_data2
0 1.236062 -0.576333 a one -0.883525 -0.799517
1 -1.925623 -0.874375 a two -0.883525 -0.799517
4 -1.961012 -0.947843 a one -0.883525 -0.799517
2 1.472156 -0.005463 b one 0.658195 1.156590
3 -0.155766 2.318643 b two 0.658195 1.156590
key = ['one', 'two', 'one', 'two',  'one']

people.groupby(key).mean()
Out[57]:
a b c d e
one 0.047710 0.105085 1.411375 -0.941295 0.897728
two 0.463261 -0.537216 0.500752 -0.407717 0.021231 people.groupby(key).transform(np.mean)
Out[58]:
a b c d e
joe 0.047710 0.105085 1.411375 -0.941295 0.897728
Steve 0.463261 -0.537216 0.500752 -0.407717 0.021231
Wes 0.047710 0.105085 1.411375 -0.941295 0.897728
Jim 0.463261 -0.537216 0.500752 -0.407717 0.021231
Travis 0.047710 0.105085 1.411375 -0.941295 0.897728

不难看出,transform会将一个函数应用到各个分组,然后将结果放置到适当的位置上

假设想从各分组中减去平均值,先创建一个距平化函数,然后将其传给transform

def demean(arr):
return arr - arr.mean() demeaned = people.groupby(key).transform(demean) demeaned
Out[60]:
a b c d e
joe -0.284934 -0.688315 1.094810 1.705641 1.730852
Steve -0.588820 0.351658 -0.726942 -1.216794 -1.010014
Wes 0.290063 NaN NaN -1.548084 -0.962657
Jim 0.588820 -0.351658 0.726942 1.216794 1.010014
Travis -0.005129 0.688315 -1.094810 -0.157557 -0.768195

【学习】数据聚合和分组运算【groupby】的更多相关文章

  1. pandas聚合和分组运算——GroupBy技术(1)

    数据聚合与分组运算——GroupBy技术(1),有需要的朋友可以参考下. pandas提供了一个灵活高效的groupby功能,它使你能以一种自然的方式对数据集进行切片.切块.摘要等操作.根据一个或多个 ...

  2. Python 数据分析(二 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识

    Python 数据分析(二) 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识 第1节 groupby 技术 第2节 数据聚合 第3节 分组级运算和转换 第4 ...

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

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

  4. 《python for data analysis》第九章,数据聚合与分组运算

    # -*- coding:utf-8 -*-# <python for data analysis>第九章# 数据聚合与分组运算import pandas as pdimport nump ...

  5. Python 数据分析—第九章 数据聚合与分组运算

    打算从后往前来做笔记 第九章 数据聚合与分组运算 分组 #生成数据,五行四列 df = pd.DataFrame({'key1':['a','a','b','b','a'], 'key2':['one ...

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

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

  7. 《利用python进行数据分析》读书笔记--第九章 数据聚合与分组运算(一)

    http://www.cnblogs.com/batteryhp/p/5046450.html 对数据进行分组并对各组应用一个函数,是数据分析的重要环节.数据准备好之后,通常的任务就是计算分组统计或生 ...

  8. 利用python进行数据分析之数据聚合和分组运算

    对数据集进行分组并对各分组应用函数是数据分析中的重要环节. group by技术 pandas对象中的数据会根据你所提供的一个或多个键被拆分为多组,拆分操作是在对象的特定轴上执行的,然后将一个函数应用 ...

  9. python数据分析之:数据聚合与分组运算

    在数据库中,我们可以对数据进行分类,聚合运算.例如groupby操作.在pandas中同样也有类似的功能.通过这些聚合,分组操作,我们可以很容易的对数据进行转换,清洗,运算.比如如下图,首先通过不同的 ...

随机推荐

  1. js相关用法

    一.location1.返回当前网址urllocation.href2.设置跳转网址urllocation.href = "http://www.baidu.com"3.重载刷新l ...

  2. IIC详解

    (1)概述 I2C(Inter-Integrated Circuit BUS) 集成电路总线,该总线由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距 ...

  3. git忽视上传规则文件 .gitignore

    语法 语法 作用 例子 "/" 忽略根目录下的文件 /data "*" 忽略所有文件 *.txt => 1.txt,2.txt... "?&qu ...

  4. 大数据量下的SQL Server数据库自身优化

    原文: http://www.d1net.com/bigdata/news/284983.html 1.1:增加次数据文件 从SQL SERVER 2005开始,数据库不默认生成NDF数据文件,一般情 ...

  5. 火狐firebug和firepath插件安装方法(最新)

    火狐浏览器最近下掉了firebug和firepath插件,用户即使下载了火狐55以下的版本,也无法查找到这两个插件. 因此,可以用以下方法来获取这两个插件. 1.下载火狐55以内版本安装包,安装时迅速 ...

  6. 面试题-Python高级

    元类 Python 中类方法.类实例方法.静态方法有何区别? 类方法:是类对象的方法,在定义时需要在上方使用“@classmethod”进行装饰,形参为cls, 表示类对象,类对象和实例对象都可调用: ...

  7. idea调试代码跟踪到tomcat代码里面

    在POM.xml文件里面加上如下代码即可: <dependency> <groupId>org.apache.tomcat</groupId> <artifa ...

  8. imp 导入报错

    imp user/passwd file=/data/oracle/oraclesetup/passwd.dmp 报错: Export file created by EXPORT:V11.02.00 ...

  9. 优化IIS7.5支持10万个同时请求的配置方法

    通过对IIS7的配置进行优化,调整IIS7应用池的队列长度,请求数限制,TCPIP连接数等方面,从而使WEB服务器的性能得以提升,保证WEB访问的访问流畅. IIS7.5是微软推出的最新平台IIS,性 ...

  10. 调整Eclipse中代码字体字号

    Window-->preferences-->general-->appearence-->Colors and fonts中的Basic节点选text font,Edit一下