pandas 数据聚合与分组运算

目录

一、分组

1.Groupby分组

2.对分组进行迭代 

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

 4.通过函数进行分组

5.根据索引级别分组

 二、聚合

 1.agg()聚合

2.transform()

3.filter()-过滤

4.apply()


一、分组

1.Groupby分组

当源数据是DataFrame类型时,groupby()方法返回一个DataFrameGroupBy对象。

若源数据是Series类型,则返回SeriesGroupBy对象。

import numpy as np
from pandas import DataFrame,Series
 
#(1)运行numpy的groupby方法分组
df=DataFrame({'key1':['a','a','b','b','a'],
               'key2':['one','two','one','two','one'],
               'data1':np.random.randn(5),
               'data2':np.random.randn(5)})
print (df)

  此时的df是dataframe对象

grouped是一个GroupBy对象,它实际上还没有进行任何计算,只是含有一些有关分组键df['key1']的中间数据而己。

换句话说,该对象已经有了接下来对各分组执行运算所需的一切信息。

我们可以调用GroupBy的mean方法来计算分组平均值,也可以调用其他方法。

grouped=df['data1'].groupby(df['key1']) #data1数据按key1进行分组
print(grouped)

grouped0=df['data1'].groupby(df['key1']).mean()
print(grouped0)

groupedall=df.groupby(df['key1']).mean()#data1数据进行分组
print(groupedall)

grouped1=df['data1'].groupby([df['key1'],df['key2']]).mean()
print(grouped1)

df.groupby(['key1','key2'])[['data1']].mean()
#grouped1=df['data1'].groupby([df['key1'],df['key2']]).mean()效果一样

2.对分组进行迭代 

for name,group in df.groupby('key1'):
    print (name)#就是a,b
    print (group)#df的一部分

for k1,group in df.groupby(['key1','key2']):
     print (k1)#('a', 'one')('a', 'two')('b', 'one')('b', 'two')
     print(group)

                              

 当然,你可以对这些数据片段做任何操作。有一个有用的运算:将这些数据片段做成一个字典:dict(list(df.groupby('')))

pieces=list(df.groupby('key1'))
pieces#是两个元胞的列表,两个元胞均有两个元素,一个是字母,一个是dataframe对象
print(pieces)
dpieces=dict(list(df.groupby('key1')))#将列表pieces转化为字典 键:a,b 值:两个表
print(dpieces)

groupby默认是在axis=0(行)上进行分组,通过设置也可以在其他任何轴上进行分组:axis=1(列)

print (df.dtypes)

grouped=df.groupby(df.dtypes,axis=1)#键:dtype('float64') dtype('O'),值:表的一部分
print (dict(list(grouped)))

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

import numpy as np
from pandas import DataFrame,Series
 
people=DataFrame([[1,0,1,2,1],
                  [0,2,3,1,0],
                  [1,2,3,0,1],
                  [-1,0,-1,2,0],
                  [2,3,1,-2,0]],
                 columns=['a','b','c','d','e'],
                 index=['Joe','Steve','Wes','Jim','Travis'])
people.ix[2:3,['b','c']]=np.nan  #ix[2:3]行索引为[2:3],索引切片不包括3,'b','c'列的值为Nan
print(people)

#(1)假设己知列的分组关系,并希望根据分组计算列的总计:
mapping={'a':'red','b':'red','c':'blue',
         'd':'blue','e':'red','f':'orange'}
#现在只需将这个字典传给groupby即可:
by_column=people.groupby(mapping,axis=1)
print (by_column.sum())
#输出结果如下:'c','d'相加存入blue中,其它的相加放入red中

 #(2) Series也有同样的功能,它可以被看做一个固定大小的映射。
#对于上面的那个例子,如果用Series作为分组键,则pandas会检查Series以确保其索引跟分组轴是对齐的:
map_series=Series(mapping)
print (map_series)
print (people.groupby(map_series,axis=1).count())

      

 4.通过函数进行分组

print(​​​​ people.groupby(len).sum())#3是Joe,wes,Jim 在a,b,c,d,e列相加
                                 #5只有steve一个人,故steve的数据抄下来即可

key_list=['one','one','one','two','two']
#将函数跟数组、列表、字典、Series混合使用,因为任何东西最终都会被转换为数组:
print(people.groupby([len,key_list]).min())

    

5.根据索引级别分组

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

import numpy as np
from pandas import DataFrame,Series
import pandas as pd
#构建多级索引列
columns=pd.MultiIndex.from_arrays([['US','US','US','JP','JP'],
                                   [1,3,5,1,3]],names=['cty','tenor'])

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

 
print (hier_df.groupby(level='cty',axis=1).count())  #axis=1列分组,count是取总计的个数

 二、聚合

通过GroupBy对象提供的agg()、transform()、filter()以及apply()等方法可以实现各种分组运算。每个方法的第一个参数都是一个回调函数函数对每个分组的数据进行运算并返回结果。这些方法根据回调函数的返回结果生成最终的分组运算结果。

 1.agg()聚合

agg()对每个分组中的数据进行聚合运算。其回调函数接收的数据是表示每个分组中每列数据的Series对象,若回调函数不能处理
Series对象,则agg()会接着尝试将整个分组的数据作为DataFrame对象传递给回调函数。下面的其他方法也是如此。

回调函数对其参数进行聚合运算,将Series对象转换为单个数值,或将DataFrame对象转换为Series对象。

agg()返回一个DataFrame对象,其行索引为每个分组的键,而列索引为源数据的列索引。

import numpy as np
from pandas import DataFrame,Series
import pandas as pd
 
df=DataFrame({'key1':['a','a','b','b','a'],
               'key2':['one','two','one','two','one'],
               'data1':np.random.randn(5),
               'data2':np.random.randn(5)})

grouped=df.groupby('key1')

#自定义函数 
def peak_to_peak(arr):
    return arr.max()-arr.min()
print (grouped.agg(peak_to_peak))

#匿名函数
#df.groupby('key1').agg(lambda df:df.max()-df.min())

  

df=pd.DataFrame([[1,2],[5,6],[9,4],[7,0],[3,8]],columns=['A','B'])
df['key']=['a','a','a','b','b']
print(df)
g=df.groupby('key')

"""
由
于np.max()能对Series对象进行运算,因此agg()将分组a和分组b中的每列数据分别传递给
np.max()以计算每列的最大值,并将所有最大值聚合成一个DataFrame对象。

"""
print(g.agg(np.max))

"""
由于在回调函数中访问了属性A和B,这两个属性在表示每列数据的Series对象中不存在,因此传递Series对象给回调函数的尝试失败。于是agg()接下来尝试将表示整个分组数据的DataFrame对象传递给回调函数。该回调函数每次返回结果中的一行,例如图中分组b对应的运算结果为第b行。该回调函数返回每个分组中A+B最大的那一行。
"""
print(g.agg(lambda df:df.loc[(df.A+df.B).idxmax()]))

      

2.transform()

 transform中传入的函数只能返回两种结果,可以广播的标量值或者与分组大小相同的结果数组。

"对分组求均值,然后把这个最小值赋值给整个组(可广播的标量值)"
print(g.transform(np.min))
"使用transform实现去最小值(返回与分组大小相同的结果数组)"
print(g.transform(lambda s:s-s.min()))

   

3.filter()-过滤

filter()对每个分组进行条件判断。它将表示每个分组的DataFrame对象传递给回调函数,该函数返回True或False,以决定是否保留该分组。filter()的返回结果是过滤掉一些行之后的DataFrame对象,其行索引与源数据的行索引的顺序一致。 

4.apply()

apply会将分组传递给函数,然后尝试将函数的返回结果组合起来。

df = DataFrame({'类别':['水果','水果','水果','蔬菜','蔬菜','肉类','肉类'],
                '产地':['美国','中国','中国','中国','新西兰','新西兰','美国'],
                '水果':['苹果','梨','草莓','番茄','黄瓜','羊肉','牛肉'],
               '数量':[5,5,9,3,2,10,8],
               '价格':[5,5,10,3,3,13,20]})
print(df)
def get_rows(df,n=2): # 返回分组的前n行数据
    return df.iloc[:n,:]
print(df.groupby('类别').apply(get_rows))

  

参考资源:https://blog.csdn.net/u012474716/article/details/81083895 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章