文章目录
分组与聚合的原理
在Pandas中,
分组
是指使用特定的条件将原数据划分为多个组,聚合
在这里指的是,对每个分组中的数据执行某些操作,最后将计算的结果进行整合。
Pandas官方参考文档地址
分组与聚合的过程大概分为以下三步:
分组与聚合的原理
通过groupby()方法将数据拆分成组
在Pandas中,可以通过
groupby()
方法将数据集按照某些标准划分成若干个组。
groupby(by=None, axis=0, level=None, as_index=True, sort=True,group_keys=True, squeeze=False, observed=False, **kwargs)
by
:用于确定进行分组的依据。axis
:表示分组轴的方向。sort
:表示是否对分组标签进行排序,接收布尔值,默认为True
。
groupby()
方法会返回一个GroupBy
对象,该对象实际上并没有进行任何计算,只是包含一些关于分组键的中间数据而已。
- 使用Series调用
groupby()
方法返回的是SeriesGroupBy对象。 - 使用DataFrame调用
groupby()
方法返回的是DataFrameBy对象。
通过
groupby()
方法的by参数
可以指定按什么标准分组,该参数可以接收的数据主要有以下4种:
列表或数组 | DataFrame某列 | 字典或Series对象 | 函数 |
---|
按列名进行分组
如果DataFrame对象的某一列数据符合划分成组的标准,则可以将该列当做分组键来拆分数据集。
df.groupby(by='Key')
#<DataFrameGroupBy object at 0x0000000006E274A8>
如果要查看每个分组的具体内容,则可以使用for循环遍历DataFrameGroupBy对象。
group_obj = df.groupby('Key')
# 遍历分组对象
for i in group_obj:
print(i)
按Series对象进行分组
还可以将自定义的Series类对象作为分组键进行分组。
ser_obj = pd.Series(['a', 'b', 'c', 'a', 'b'])
# 按自定义Series对象进行分组
group_obj = df.groupby(by = ser_obj)
思考:
如果Series对象的长度与原数据的行索引长度不相等时,那么在分组时会怎么样呢?
答:
如果Series对象与Pandas对象的索引长度不相同时,则只会将具有相同索引的部分数据进行分组。
df = se = pd.Series(['a', 'a', 'b'])
group_obj = df.groupby(se)['one', 'two', 'one','two', 'one'],
'data1': [2, 3, 4, 6, 8],
'data2': [3, 5, 6, 3, 7]})
se = pd.Series(['a', 'a', 'b'])
group_obj = df.groupby(se)
按字典进行分组
当使用字典对DataFrame进行分组时,则需要确定轴的方向及字典中的映射关系,即字典中的键为列名,字典的值为自定义的分组名。
mapping = {'a':'第一组','b':'第二组','c':'第一组','d':'第三组','e':'第二组'}
by_column = num_df.groupby(mapping, axis=1)
按函数进行分组
将函数作为分组键会更加灵活,任何一个被当做分组键的函数都会在各个索引值上被调用一次,返回的值会被用作分组名称。
# 使用内置函数len进行分组
groupby_obj = df.groupby(len)
数据聚合
使用内置统计方法聚合数据
前面介绍过的Pandas统计方法,比如用于获取最大值和最小值的
max()
和mix()
,这些方法常用于简单地聚合分组中的数据。
# 按key1进行分组,求每个分组的平均值
df.groupby('key1').mean()
面向列的聚合方法
如果内置方法无法满足聚合要求时,则可以自定义函数,将它作为参数传给
agg()
方法,实现Pandas对象的聚合运算。
agg(func,axis = 0,* args,** kwargs )
func
:表示用于汇总数据的函数,可以为单个函数或函数列表。axis
:表示函数作用于轴的方向,0
或index
表示将函数应用到每一列;columns
表示将函数应用到每一行,该参数的默认值为0
。
对每一列数据应用同一个函数
通过
agg()
方法进行聚合,最简单的方式就是给该方法的func
参数传入一个函数,这个函数既可以是内置的,也可以自定义的。
def range_data_group(arr):
return arr.max()-arr.min()
# 使用自定义函数聚合分组数据
data_group.agg(range_data_group)
对某列数据应用不同的函数
可以将两个函数的名称放在列表中,之后在调用
agg()
方法进行聚合时作为参数传入即可,
# 对一列数据用两种函数聚合
data_group.agg([range_data_group, sum])
虽然每一列可以应用不同的函数,但是结果并不能很直观地辨别出每个函数代表的含义。
为了能更好地反映出每列数据的信息,可以使用
“(name,function)”
元组将function(函数名)
替换为name(自定义名称)
。
data_group.agg([("极差", range_data_group), ("和", sum)])
对不同列数据应用不同函数
如果希望对不同的列使用不同的函数,则可以在
agg()
方法中传入一个{"列名":"函数名"}
格式的字典。
data_group.agg({'a': 'sum', 'b': 'mean', 'c': range_data_group})
agg()
方法执行聚合操作时,会将一组标量值参与某些运算后转换为一个标量值。
分组级运算
数据转换
思考:
如果希望聚合后的数据与原数据保持一样的形状,应该怎么做呢?
答:
如果希望保持与原数据集形状相同,那么可以通过
transfrom()
方法实现。
transform(func, *args, **kwargs)
- 上述方法中只有一个
func
参数,表示操作Pandas对象的函数。 transfrom()
方法会把func
函数应用到各个分组中,并且将计算结果放在适当的位置上。
transform()
方法返回的结果有两种,一种是可以广播的标量值(np.mean)
,另一种可以是与分组大小相同的结果数组。
数据应用
apply()
方法的使用是十分灵活的,它可以在许多标准用例中替代聚合和转换,另外还可以处理一些比较特殊的用例。
apply(func, axis=0, broadcast=None, raw=False, reduce=None,result_type=None, args=(), **kwds)
func
:表示应用于某一行或某一列的函数。axis
:表示函数操作的轴向。broadcast
:表示是否将数据进行广播。
本章小结
- 本章主要针对Pandas的分组聚合和其它组内运算进行了介绍,包括分组与聚合的原理、分组操作、聚合操作,以及其它分组级的相关操作,最后介绍了一个分析运动员基本信息的案例,真实地演示如何运用这些知识。
- 大家在学习与理解的同时,要多加练习,可根据具体情况选择合理的技术进行运用即可。