1、groupby主要用于数据的某些标签或索引的局部进行累计分析,大致过程为输入,分割,应用,组合。
import numpy as np
import pandas as pd
df = pd.DataFrame({'key':['A','B','C','A','B','C'],
'data':range(6)},columns = ['key','data'])
OUT:
key data
0 A 0
1 B 1
2 C 2
3 A 3
4 B 4
5 C 5
df.groupby('key')
#返回值为
#返回值不是一个DataFrame对象,而是DataFrameGroupBy对象。可以将它看作是特殊形式的DataFrame,里
#隐藏着若干组数据,但是在没有应用累计函数之前不会计算,可以理解为“延迟计算”。
df.groupby('key').sum()
OUT:
data
key
A 3
B 5
C 7
2、Group对象
(1)按列取值:GroupBy对象与DataFrame一样,支持按列取值,并返回一个修改过的GroupBy对象;
(2)按组迭代:GroupBy对象支持直接按组迭代,返回每一组都是Series或DataFrame;
3、累计,过滤,转换,应用(aggregate(),filter(),transform(),apply())
df = pd.DataFrame({'key':['A','B','C','A','B','C'],
'data1':range(6),
'data2':rng.randint(0,10,6)},
columns = ['key','data1','data2'])
OUT:
key data1 data2
0 A 0 5
1 B 1 0
2 C 2 3
3 A 3 3
4 B 4 7
5 C 5 9
(1)累计
df.groupby('key').aggregate(['min',np.median,max])
OUT:
data1 data2
min median max min median max
key
A 0 1.5 3 3 4.0 5
B 1 2.5 4 0 3.5 7
C 2 3.5 5 3 6.0 9
#指定不同列需要累积的函数
df.groupby('key').aggregate({'data1':'min',
'data2':'max'})
OUT:
data1 data2
key
A 0 5
B 1 7
C 2 9
(2)过滤:过滤操作可以让你按照分组的属性丢弃若干数据。
#只保留标准差超过某个阈值的组
def filter_func(x):
return x['data2'].std() > 4
print(df)
print(df.groupby('key').std())
print(df.groupby('key').filter(filter_func))
#filter()函数会返回一个布尔值,表示每组是否通过过滤。由于A组‘data2’列的标准差不大于4,所以被丢
##弃。
OUT:
key data1 data2
0 A 0 5
1 B 1 0
2 C 2 3
3 A 3 3
4 B 4 7
5 C 5 9
data1 data2
key
A 2.12132 1.414214
B 2.12132 4.949747
C 2.12132 4.242641
key data1 data2
1 B 1 0
2 C 2 3
4 B 4 7
5 C 5 9
(3)转换。累计操作返回的是对组内全部数据缩减的结果,而转换操作会返回一个全新的数据。数据经过转换之后,其形状与原来的输入数据是一样的。常见的例子就是将每一组的样本数据减去各组对应的均值,实现数据标准化。
#将数据标准化
sd = df.groupby('key').transform(lambda x : x-x.mean())
print(sd)
OUT:
data1 data2
0 -1.5 1.0
1 -1.5 -3.5
2 -1.5 -3.0
3 1.5 -1.0
4 1.5 3.5
5 1.5 3.0
(4)应用,apply()方法可以让你在每个组上应用任意方法。这个函数输入一个DataFrame,返回一个Pandas对象(DataFrame或Series)或者一个标量(scalar,单个数值)。组合操作会对应返回结果类型。
#用apply()方法将第一列数据以第二列的和为基数进行标准化
def norm_by_data2(x):
#x是一个分组数据的DataFrame
x['data1'] /= x['data2'].sum()
return x
print(df)
print(df.groupby('key').apply(norm_by_data2))
OUT:
key data1 data2
0 A 0 5
1 B 1 0
2 C 2 3
3 A 3 3
4 B 4 7
5 C 5 9
key data1 data2
0 A 0.000000 5
1 B 0.142857 0
2 C 0.166667 3
3 A 0.375000 3
4 B 0.571429 7
5 C 0.416667 9
4、设置分给键:前面的例子一直用列名分割DataFrame,这只是众多分组操作中的一种。
(1)将列表,数组,Series或索引作为分组键。分组键可以是长度与DataFrame匹配的任意series或列表。
L = [0,1,0,1,2,0]
print(df)
print(df.groupby(L).sum())#分别对第1,3,6; 2,4 和5行求和
OUT:
key data1 data2
0 A 0 5
1 B 1 0
2 C 2 3
3 A 3 3
4 B 4 7
5 C 5 9
data1 data2
0 7 17
1 4 3
2 4 7
(2)用字典或Series将索引映射到分组名称。
df2 = df.set_index('key')
mapping = {'A':'vpwel','B':'consonant','C':'consonant'}
print(df)
print(df2)
print(df2.groupby(mapping).sum())
#注意不能直接print(df.groupby(mapping).sum())
#此时out结果为
#Empty DataFrame
#Columns: [data1, data2]
#Index: []
OUT:
key data1 data2
0 A 0 5
1 B 1 0
2 C 2 3
3 A 3 3
4 B 4 7
5 C 5 9
data1 data2
key
A 0 5
B 1 0
C 2 3
A 3 3
B 4 7
C 5 9
data1 data2
consonant 12 19
vpwel 3 8
(3)任意Python函数,可以将任意Python函数传入groupby,函数映射到索引,然后新的分组输出
print(df2.groupby(str.lower).mean())
#将索引转换为小写
OUT:
data1 data2
a 1.5 4.0
b 2.5 3.5
c 3.5 6.0
(4)多个有效键,构成的列表
print(df2.groupby([str.lower,mapping]).mean())
OUT:
data1 data2
a vpwel 1.5 4.0
b consonant 2.5 3.5
c consonant 3.5 6.0