目录
一、分组
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