在数据分析过程中经常需要对数据集进行分组,并且统计均值,最大值等等。那么 groupby()
的学习就十分有必要了
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, observed=False, dropna=True)
A groupby operation involves some combination of splitting the object, applying a function, and combining the results. This can be used to group large amounts of data and compute operations on these groups.
Parameters:
Returns:
DataFrameGroupBy
, Returns a groupby object that contains information about the groups.
生成一个学生数据集,包含身高和成绩:
import pandas as pd
import numpy as np
classes = ["A", "B", "C"]
student = pd.DataFrame({
'class': [classes[x] for x in np.random.randint(0,len(classes),10)],
'height': np.random.randint(150, 190, 10),
'score': np.random.randint(50, 100, 10)
})
按班级分组:
# 按班级分组
group = student.groupby('class')
# pandas.core.groupby.generic.DataFrameGroupBy
type(group)
list(group)
的结果是:
Out[]:
[('A',
class height score score_mean
3 A 167 65 74.333333
8 A 163 73 74.333333
9 A 167 85 74.333333),
('B',
class height score score_mean
1 B 175 76 59.666667
6 B 151 53 59.666667
7 B 185 50 59.666667),
('C',
class height score score_mean
0 C 166 65 71.0
2 C 185 61 71.0
4 C 183 59 71.0
5 C 182 99 71.0)]
可以看到,groupby的过程将整个df按照指定的字段分为若干个子df
之后的agg、apply等操作都是对子df的操作
常见的有:
# 聚合操作之后的返回值类型为dataframe
a = student.groupby('class').agg('mean')
a = group.agg('mean')
# 可以用字典来指定对不用的列求不同的值
b = student.groupby('class').agg({'score':'mean','height':'median'})
a:
Out[]:
height score
class
A 165.666667 74.333333
B 170.333333 59.666667
C 179.000000 71.000000
b:
Out[26]:
score height
class
A 74.333333 167.0
B 59.666667 175.0
C 71.000000 182.5
agg()
是返回统计的结果,返回值为df
transform()
对每一条数据进行处理, 相同组有相同的结果, 组内求完均值后会按照原索引的顺序返回结果
返回series
如果要在student上加一列学生所在班级的平均分
不使用transform需要两步:
# 1.先得到班级平均值的dict
avg_score_dict = student.groupby('class')['score'].mean().to_dict()
# 2.再对每个学生根据班级map一下
student['score_mean'] = student['class'].map(avg_score_dict)
使用transform只需要一步:
student['score_mean'] = student.groupby('class')['score'].transform('mean')
能够传入任意自定义的函数,实现复杂的数据操作
注意:
假设我需要获取每个班分数最高的学生的数据:
# 获取分数最高的学生
def get_highest_student(x):
df = x.sort_values(by='score', ascending=False)
return df.iloc[0, :]
highest_student = student.groupby('class', as_index=False).apply(get_highest_student)