四时宝库

程序员的知识宝库

“拆分-应用-合并"分组运算过程,python分组技术groupby应用详解


前言

“split-apply-combine”(拆分-应用-合并)很好地描述了分组运算的整个过程。

分组运算的第一个阶段,pandas对象(无论是Series、DataFrame还是其他的)中的数据会根据所提供的一个或多个键被拆分(split)为多组。

拆分操作是在对象的特定轴上执行的。例如,DataFrame可以在其行(axis=0)或列(axis=1)上进行分组。

然后,将一个函数应用(apply)到各个分组并产生一个新值。

最后,所有这些函数的执行结果会被合并(combine)到最终的结果对象中。结果对象的形式一般取决于数据上所执行的操作。

下图,大致说明了一个简单的分组聚合过程:


分组键

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

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

注意:后三种都只是快捷方式而已,其最终目的仍然是产生一组用于拆分对象的值。

先了解一下表格型数据集(以DataFrame的形式):

In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: from pandas import Series,DataFrame
In [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]: df
Out[5]: 
  key1 key2     data1     data2
0    a  one -0.549915 -1.567342
1    a  two -0.037543 -0.834576
2    b  one -1.267072  1.628881
3    b  two  0.976757 -1.549664
4    a  one  2.423714  1.791845

假设想要按key1进行分组,并计算data1列的平均值。实现方式:访问data1,并根据key1调用groupby:

In [6]: grouped=df['data1'].groupby(df['key1'])
In [7]: grouped
Out[7]: <pandas.core.groupby.generic.SeriesGroupBy object at 0x119840240>

变量grouped是一个GroupBy对象。它实际上还没有进行任何计算,只是含有一些有关分组键df[‘key1’]的中间数据而已。换句话说,该对象已经有了接下来对各组执行运算所需的一切信息。例如,可以调用GroupBy的mean方法来计算分组平均值:

In [8]: grouped.mean()
Out[8]: 
key1
a    0.612085
b   -0.145158
Name: data1, dtype: float64

四种分组键使用方法,具体如下:

一次传入多个数组

In [9]: means=df['data1'].groupby([df['key1'],df['key2']]).mean()
In [10]: means
Out[10]: 
key1  key2
a     one     0.936899
      two    -0.037543
b     one    -1.267072
      two     0.976757
Name: data1, dtype: float64

通过两个键对数据进行了分组,得到的Series具有一个层次化索引(由唯一的键对组成):

In [11]: means.unstack()
Out[11]: 
key2       one       two
key1                    
a     0.936899 -0.037543
b    -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.267072
Ohio        2005    0.213421
            2006    2.423714
Name: data1, dtype: float64

将列名(可以是字符串、数字或其他python对象)用作分组键

In [15]: df.groupby('key1').mean()
Out[15]: 
         data1     data2
key1                    
a     0.612085 -0.203358
b    -0.145158  0.039609

在执行df.groupby('key1').mean()时,结果中没有key2列。这是因为df[‘key2’]不是数值数据(俗称“麻烦列”),所以被从结果中排除了。默认情况下,所有数据列都会被整合,虽然有时会被过滤为一个子集。

In [16]: df.groupby(['key1','key2']).mean()
Out[16]: 
              data1     data2
key1 key2                    
a    one   0.936899  0.112251
     two  -0.037543 -0.834576
b    one  -1.267072  1.628881
     two   0.976757 -1.549664

GroupBy的size方法

返回一个含有分组大小的Series:

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

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接