【Pandas学习笔记Task04】:分组
- 一、分组模式及其对象
- 1.分组的一般模式
- 2.分组依据的本质
- 3.Groupby对象
- 二、聚合函数
- 1.内置聚合函数
- 2.agg方法
- 三、变换和过滤
- 1.变换函数与transform方法
- 2.组索引与过滤
- 四、跨列分组
- 1. apply的使用
import numpy as np
import pandas as pd
df = pd.read_csv('data/learn_pandas.csv')
一、分组模式及其对象
1.分组的一般模式
想要实现分组操作,需要明确三个要素:分组依据、数据来源、操作及其返回结果。
分组其实也就相当于在原来对整列的操作上,将列划分为几部分。就比如下面的根据性别统计身高。性别是依据,可以理解为将身高列中的数据,先根据性别化为两部分(性别只有俩值),然后分别操作就行了。
# 按照性别统计身高的中位数。
df.groupby('Gender')['Height'].median()
Gender
Female 159.6
Male 173.4
Name: Height, dtype: float64
2.分组依据的本质
对多个维度分组,只需要在groupby中传入一个列表就行。
item = np.random.choice(list('abc'), df.shape[0])
df.groupby(item)['Height'].mean()
a 163.571429
b 163.244444
c 162.962195
Name: Height, dtype: float64
# df.groupby(['School', 'Gender'])['Height'].mean()
df.groupby([df['School'], df['Gender']])['Height'].mean()
School Gender
Fudan University Female 158.776923
Male 174.212500
Peking University Female 158.666667
Male 172.030000
Shanghai Jiao Tong University Female 159.122500
Male 176.760000
Tsinghua University Female 159.753333
Male 171.638889
Name: Height, dtype: float64
3.Groupby对象
gb = df.groupby(['School','Gender'])
gb.ngroups # 得到分组个数
8
res = gb.groups # groups可以得到每个组以及其值的字典
res.keys()
dict_keys([('Fudan University', 'Female'), ('Fudan University', 'Male'), ('Peking University', 'Female'), ('Peking University', 'Male'), ('Shanghai Jiao Tong University', 'Female'), ('Shanghai Jiao Tong University', 'Male'), ('Tsinghua University', 'Female'), ('Tsinghua University', 'Male')])
gb.size() #返回的是每个组值的个数
School Gender
Fudan University Female 30
Male 10
Peking University Female 22
Male 12
Shanghai Jiao Tong University Female 41
Male 16
Tsinghua University Female 48
Male 21
dtype: int64
# 只能传列名
gb.get_group(('Fudan University', 'Female')).iloc[:3,:3]# 这里去掉了名字所在的列。(我理解相当于当做索引了)
School | Grade | Name | |
3 | Fudan University | Sophomore | Xiaojuan Sun |
15 | Fudan University | Freshman | Changqiang Yang |
26 | Fudan University | Junior | Yanli You |
二、聚合函数
1.内置聚合函数
2.agg方法
【a】使用多个函数
【b】对特定的列使用特定的聚合函数
【c】使用自定义函数
gb = df.groupby('Gender')[['Height','Weight']]
gb.agg(['mean', 'idxmax', 'skew']) # 多个函数直接传列表
gb.agg({'Height':['mean','max'],'Weight':'count'}) # 对特定列执行特定聚合函数的话传字典
gb.agg(lambda x: x.mean() - x.min()) # 自定义函数
#这里想到apply。apply针对的是未分组前的df,对整列求。这个agg是对分组后所在组的列分别求
Height | Weight | |
Gender | ||
Female | 13.79697 | 13.918519 |
Male | 17.92549 | 21.759259 |
# 对聚合结果重命名
gb.agg([('range', lambda x: x.max() - x.min())]) # 将a传的列表中的函数名字改为自定义元组。
Height | Weight | |
range | range | |
Gender | ||
Female | 24.8 | 29.0 |
Male | 38.2 | 38.0 |
三、变换和过滤
1.变换函数与transform方法
gb.cummax().head()# 完成的是组内累积操作。与聚合函数类似
Height | Weight | |
0 | 158.9 | 46.0 |
1 | 166.5 | 70.0 |
2 | 188.9 | 89.0 |
3 | NaN | 46.0 |
4 | 188.9 | 89.0 |
# 自定义变换利用transform方法。
gb.transform(lambda x: (x-x.mean())/x.std()).head()
Height | Weight | |
0 | -0.058760 | -0.354888 |
1 | -1.010925 | -0.355000 |
2 | 2.167063 | 2.089498 |
3 | NaN | -1.279789 |
4 | 0.053133 | 0.159631 |
gb.transform('mean').head() # 标量广播
# 构造两列新特征来分别表示样本所在性别组的身高均值和体重均值
# gb.agg('mean').head()
# 这里可以理解将聚合的值加到新的列中。
Height | Weight | |
0 | 159.19697 | 47.918519 |
1 | 173.62549 | 72.759259 |
2 | 173.62549 | 72.759259 |
3 | 159.19697 | 47.918519 |
4 | 173.62549 | 72.759259 |
2.组索引与过滤
之前的索引是对所有行进行筛选,而组过滤可以理解为是在一个组内对所有行进行筛选。
gb.filter(lambda x: x.shape[0] > 100).head()
Height | Weight | |
0 | 158.9 | 46.0 |
3 | NaN | 41.0 |
5 | 158.0 | 51.0 |
6 | 162.5 | 52.0 |
7 | 161.9 | 50.0 |
df[['Height','Weight']].shape
(200, 2)
四、跨列分组
1. apply的使用
# 对多列同时处理
gb.apply(lambda x: (x['Weight']/(x['Height']/100)**2).mean())
Gender
Female 18.860930
Male 24.318654
dtype: float64
gb = df.groupby(['Gender','Test_Number'])[['Height','Weight']]
gb.apply(lambda x: 0)
Gender Test_Number
Female 1 0
2 0
3 0
Male 1 0
2 0
3 0
dtype: int64
gb.apply(lambda x: [0, 0]) # 这里列表仍然看作标量(emmm)。
Gender Test_Number
Female 1 [0, 0]
2 [0, 0]
3 [0, 0]
Male 1 [0, 0]
2 [0, 0]
3 [0, 0]
dtype: object
gb.apply(lambda x: pd.Series([0,0],index=['a','b']))
a | b | ||
Gender | Test_Number | ||
Female | 1 | 0 | 0 |
2 | 0 | 0 | |
3 | 0 | 0 | |
Male | 1 | 0 | 0 |
2 | 0 | 0 | |
3 | 0 | 0 |
gb.apply(lambda x: pd.DataFrame(np.ones((2,2)),
index = ['a','b'],
columns=pd.Index([('w','x'),('y','z')])))
w | y | |||
x | z | |||
Gender | Test_Number | |||
Female | 1 | a | 1.0 | 1.0 |
b | 1.0 | 1.0 | ||
2 | a | 1.0 | 1.0 | |
b | 1.0 | 1.0 | ||
3 | a | 1.0 | 1.0 | |
b | 1.0 | 1.0 | ||
Male | 1 | a | 1.0 | 1.0 |
b | 1.0 | 1.0 | ||
2 | a | 1.0 | 1.0 | |
b | 1.0 | 1.0 | ||
3 | a | 1.0 | 1.0 | |
b | 1.0 | 1.0 |
总结:本次学习尚有很多内容未理解透彻,还需继续补充。