前言
“split-apply-combine”(拆分-应用-合并)很好地描述了分组运算的整个过程。
分组运算的第一个阶段,pandas对象(无论是Series、DataFrame还是其他的)中的数据会根据所提供的一个或多个键被拆分(split)为多组。
拆分操作是在对象的特定轴上执行的。例如,DataFrame可以在其行(axis=0)或列(axis=1)上进行分组。
然后,将一个函数应用(apply)到各个分组并产生一个新值。
最后,所有这些函数的执行结果会被合并(combine)到最终的结果对象中。结果对象的形式一般取决于数据上所执行的操作。
下图,大致说明了一个简单的分组聚合过程:
分组键
分组键可以有多种形式,且类型不必相同:
- 列表或数组,其长度与待分组的轴一样。
- 表示DataFrame某个列名的值。
- 字典或Series,给出待分组轴上的值与分组名之间的对应关系。
- 函数,用于处理轴索引中的各个标签。
注意:后三种都只是快捷方式而已,其最终目的仍然是产生一组用于拆分对象的值。
先了解一下表格型数据集(以DataFrame的形式):
In [1]: import numpy as npIn [2]: import pandas as pdIn [3]: from pandas import Series,DataFrameIn [4]: df=DataFrame({'key1':['a','a','b','b','a'], 'key2':['one','two','one','two','one'], 'data1':np.random.randn(5), 'data2':np.random.randn(5)})In [5]: dfOut[5]: key1 key2 data1 data20 a one -0.549915 -1.5673421 a two -0.037543 -0.8345762 b one -1.267072 1.6288813 b two 0.976757 -1.5496644 a one 2.423714 1.791845
假设想要按key1进行分组,并计算data1列的平均值。实现方式:访问data1,并根据key1调用groupby:
In [6]: grouped=df['data1'].groupby(df['key1'])In [7]: groupedOut[7]:
变量grouped是一个GroupBy对象。它实际上还没有进行任何计算,只是含有一些有关分组键df[‘key1’]的中间数据而已。换句话说,该对象已经有了接下来对各组执行运算所需的一切信息。例如,可以调用GroupBy的mean方法来计算分组平均值:
In [8]: grouped.mean()Out[8]: key1a 0.612085b -0.145158Name: data1, dtype: float64
四种分组键使用方法,具体如下:
一次传入多个数组
In [9]: means=df['data1'].groupby([df['key1'],df['key2']]).mean()In [10]: meansOut[10]: key1 key2a one 0.936899 two -0.037543b one -1.267072 two 0.976757Name: data1, dtype: float64
通过两个键对数据进行了分组,得到的Series具有一个层次化索引(由唯一的键对组成):
In [11]: means.unstack()Out[11]: key2 one twokey1 a 0.936899 -0.037543b -1.267072 0.976757
分组键可以是任何长度适当的数组
In [12]: states=np.array(['Ohio','California','California','Ohio','Ohio'])In [13]: years=np.array([2005,2005,2006,2005,2006])In [14]: df['data1'].groupby([states,years]).mean()Out[14]: California 2005 -0.037543 2006 -1.267072Ohio 2005 0.213421 2006 2.423714Name: data1, dtype: float64
将列名(可以是字符串、数字或其他python对象)用作分组键
In [15]: df.groupby('key1').mean()Out[15]: data1 data2key1 a 0.612085 -0.203358b -0.145158 0.039609
在执行df.groupby('key1').mean()时,结果中没有key2列。这是因为df[‘key2’]不是数值数据(俗称“麻烦列”),所以被从结果中排除了。默认情况下,所有数据列都会被整合,虽然有时会被过滤为一个子集。
In [16]: df.groupby(['key1','key2']).mean()Out[16]: data1 data2key1 key2 a one 0.936899 0.112251 two -0.037543 -0.834576b one -1.267072 1.628881 two 0.976757 -1.549664
GroupBy的size方法
返回一个含有分组大小的Series:
In [17]: df.groupby(['key1','key2']).size()Out[17]: key1 key2a one 2 two 1b one 1 two 1dtype: int64