首页 > 其他 > 详细

Pandas中的GroupBy及agg详解

时间:2021-03-03 19:16:31      阅读:132      评论:0      收藏:0      [点我收藏+]


pandas提供了一个灵活高效的groupby功能,它使你能以一种自然的方式对数据集进行切片、切块、摘要
等操作。根据一个或多个键(可以是函数、数组或DataFrame列名)拆分pandas对象。计算分组摘要统
计,如计数、平均值、标准差,或用户自定义函数。对DataFrame的列应用各种各样的函数。应用组内转换
或其他运算,如规格化、线性回归、排名或选取子集等。计算透视表或交叉表。执行分位数分析以及其他分
组分析。
groupby()是一个分组函数,对数据进行分组操作的过程可以概括为:split-apply-combine三步:

  1. 按照键值(key)或者分组变量将数据分组。
  2. 对于每组应用我们的函数,这一步非常灵活,可以是python自带函数,可以是我们自己编写的函数。
  3. 将函数计算后的结果聚合。

  返回值:返回重构格式的DataFrame,特别注意,groupby里面的字段内的数据重构后都会变成索引
  groupby(),一般和sum()、mean()一起使用,如下例:

官网:https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html

groupby分组函数:

DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)

by : 接收映射、函数、标签或标签列表;用于确定聚合的组
axis : 接收 0/1;用于表示沿行(0)或列(1)分割。
level : 接收int、级别名称或序列,默认为None;如果轴是一个多索引(层次化),则按一个或多个特定级别分组
as_index : 接收布尔值,默认Ture;Ture则返回以组标签为索引的对象,False则不以组标签为索引

基本操作

在进行对groupby函数进行学习之前,首先需要明确的是,通过对DataFrame对象调用groupby()函数返回的结果是一个DataFrameGroupBy对象,而不是一个DataFrame或者Series对象,所以,它们中的一些方法或者函数是无法直接调用的,需要按照GroupBy对象中具有的函数和方法进行调用。

import pandas as pd
import numpy as np

df = pd.DataFrame({‘key1‘:list(‘aabba‘),
                  ‘key2‘: [‘one‘,‘two‘,‘one‘,‘two‘,‘one‘],
                  ‘data1‘: [8,6,2,4,3],
                  ‘data2‘: [6,9,5,2,-7]})

  key1 key2  data1  data2
0    a  one      8      6
1    a  two      6      9
2    b  one      2      5
3    b  two      4      2
4    a  one      3     -7 

grouped = df.groupby(‘key2‘)
print(type(grouped))
print(grouped)

#输出结果如下:
<class ‘pandas.core.groupby.generic.DataFrameGroupBy‘>
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x00000292E0778B50>

普通分组,单值分组

按key1分组并求均值

print(df.groupby(‘key1‘).mean(),‘\n‘)

         data1     data2
key1                    
a     5.666667  2.666667
b     3.000000  3.500000 

print(df.groupby(‘key1‘,as_index=False).mean(),‘\n‘)
#注意使用as_index=False和不使用的区别
  key1     data1     data2
0    a  5.666667  2.666667
1    b  3.000000  3.500000

#功能与上一句相同:print(df.groupby([‘key1‘],as_index=False).mean(),‘\n‘)

普通分组,多值分组

按states,years分组并求均值

states=np.array([‘Ohio‘,‘California‘,‘California‘,‘Ohio‘,‘Ohio‘])
years=np.array([2005,2005,2006,2005,2006])
print(df[‘data1‘].groupby([states,years]).mean(),‘\n‘)

#输出结果如下:
California  2005    6
            2006    2
Ohio        2005    6
            2006    3

指定多个列名个单个列名后的区别在于,分组的主键或者索引(indice)将一个是单个主键,另一个则是一个元组的形式:

grouped = df.groupby(‘key1‘)
grouped_muti = df.groupby([states,years])

print(grouped.size())

key1
a    3
b    2
dtype: int64

print(grouped_muti.size())

California  2005    1
            2006    1
Ohio        2005    2
            2006    1
dtype: int64

print(grouped.get_group(‘a‘))

  key1 key2  data1  data2
0    a  one      8      6
1    a  two      6      9
4    a  one      3     -7

print(grouped_muti.get_group((‘Ohio‘, 2005)))
  key1 key2  data1  data2
0    a  one      8      6
3    b  two      4      2

使用Series和字典作为分组

除了使用上述List类型的数据作为分组依据,还可以使用Series和字典作为分组依据。下面仅以字典类型为例:

import pandas as pd
import numpy as np
data=pd.DataFrame(np.arange(20).reshape(4,5),index=list(‘1234‘),columns=list(‘12345‘))
by_dict={‘1‘:‘red‘,‘2‘:‘yellow‘,‘3‘:‘yellow‘,‘4‘:‘black‘,‘5‘:‘white‘}
by_dict1={‘1‘:‘red‘,‘2‘:‘yellow‘,‘3‘:‘yellow‘,‘5‘:‘white‘}
data_1=data.groupby(by_dict)
print("按by_dict分组的结果:")
for key,group in data_1:
    print(key)
    print(group)
data_2=data.groupby(by_dict1)
print("按by_dict1分组的结果:")
data_3=data.groupby(by_dict1)
for key,group in data_3:
    print(key)
    print(group)

注意:

使用字典或Series作为依据对数据进行分组时,如果行索引或列索引在分组依据(代码中的by_dict和by_dict1变量)中并没有找到对应关系,则对应的行或列是不参与最终的分组的(不是自成一组,可以从by_dict1分组的结果中看出此结论)。
分组依据中可以出现行索引或列索引中没有出现的值。比如by_dict1中的5
使用Series和字典时,可以设置axis参数。

grouped的函数操作

通过调用get_group()函数可以返回一个按照分组得到的DataFrame对象,所以可以将DataFrameGroupBy对象理解为是多个DataFrame组成的。
而没有调用get_group()函数之前,此时的数据结构任然是DataFrameGroupBy,此时进行对DataFrameGroupBy按照列名进行索引,
就可以得到SeriesGroupBy对象,取多个列名,则得到的任然是DataFrameGroupBy对象,这里可以类比DataFrame和Series的关系。

#A single group can be selected using get_group():
grouped.get_group("bar")
#Out: 
     A      B         C         D
1  bar    one  0.254161  1.511763
3  bar  three  0.215897 -0.990582
5  bar    two -0.077118  1.211526
Or for an object grouped on multiple columns:

#for an object grouped on multiple columns:
df.groupby(["A", "B"]).get_group(("bar", "one"))

因此,在没有进行调用get_group(),也就是没有取出特定某一组数据之前,此时的数据结构任然是DataFrameGroupBy,其中也有很多函数和方法可以调用,
如max()、count()、std()等,返回的结果是一个DataFrame对象。
调用get_group()函数后得到了Series的对象,下面的操作就可以按照Series对象中的函数行了。

print(grouped.count())
print(grouped.max()[[‘Age‘, ‘Score‘]])
print(grouped.mean()[[‘Age‘, ‘Score‘]])

如果其中的函数无法满足需求,也可以选择使用聚合函数aggregate,传递numpy或者自定义的函数,前提是返回一个聚合值。
关于使用自定义对数据进行分组时,要注意以下两点:

  1. 除了自定义的函数,python中的内建函数,比如len等,也可以直接用来进行分组。(此处并没有举例)
  2. 这些函数不仅可以作用在索引列上,也可以自己指定作用列。
  3. 指定了自定义函数的作用列之后,作用列中的每个值都会传入到函数中执行。并根据其函数运行结果对原始数据进行分组。

具体可参考官网的例子:https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html

gb = df.groupby("key1")
gb.<TAB>   #(输入gb.后按Tab键,可以看到以下提示:)
gb.agg        gb.boxplot    gb.cummin     gb.describe   gb.filter     gb.get_group  gb.height     gb.last       gb.median     gb.ngroups
gb.plot       gb.rank       gb.std        gb.transform  gb.aggregate  gb.count      gb.cumprod    gb.dtype      gb.first      gb.groups 
gb.hist       gb.max        gb.min        gb.nth        gb.prod       gb.resample   gb.sum        gb.var        gb.apply      gb.cummax
gb.cumsum     gb.fillna     gb.gender     gb.head       gb.indices    gb.mean       gb.name       gb.ohlc       gb.quantile   gb.size
gb.tail       gb.weight

def getSum(data):
    total = 0
    for d in data:
        total+=d
    return total

print(grouped.aggregate(np.median))
print(grouped.aggregate({‘Age‘:np.median, ‘Score‘:np.sum}))
print(grouped.aggregate({‘Age‘:getSum}))

aggregate函数不同于apply,前者是对所有的数值进行一个聚合的操作,而后者则是对每个数值进行单独的一个操作:

def addOne(data):
    return data + 1

df[‘Age‘] = df[‘Age‘].apply(addOne)
df[‘Age‘] = df[‘Age‘].apply(int)

更复杂的agg方法

animals = pd.DataFrame({"kind": ["cat", "dog", "cat", "dog"],
"height": [9.1, 6.0, 9.5, 34.0],
"weight": [7.9, 7.5, 9.9, 198.0]})

animals.groupby("kind").agg(
min_height=pd.NamedAgg(column="height", aggfunc="min"),
max_height=pd.NamedAgg(column="height", aggfunc="max"),
average_weight=pd.NamedAgg(column="weight", aggfunc=np.mean))

对grouped里的元素进行遍历

for name, group in grouped:
    print(name)
    print(group)

通过循环,对value进行拼接。

# 循环拼接
for key, value in data_group:
    new_data = pd.concat([new_data, value])
print(new_data)

在x,y轴上进行分组

Pandas中使用groupby时默认是在axis=0轴上进行分组的,也可以通过设置在axis=1轴上进行分组。

import pandas as pd
import numpy as np
def odd(num):
    return int(num)%2==0
data=pd.DataFrame(np.arange(20).reshape(4,5),index=list(‘1234‘),columns=list(‘12345‘))
print("原始数据:")
print(data)
data_axis0=data.groupby(odd,axis=0)#默认依据index在odd上的运行结果进行分组
print("按axis=0进行分组结果如下:")
for key,group in data_axis0:
    print(key)
    print(group)
data_axis1=data.groupby(odd,axis=1)#默认依据column在odd上的运行结果进行分组
print("按axis=1进行分组结果如下:")
for key,group in data_axis1:
    print(key)
    print(group)

————————————————

参考文件:

https://blog.csdn.net/jingshuiliushen_zj/article/details/83211650
https://blog.csdn.net/m0_45210226/article/details/109406562
https://blog.csdn.net/FrankieHello/article/details/97272990
https://blog.csdn.net/brucewong0516/article/details/78768443
https://blog.csdn.net/yeshang_lady/article/details/102488971

Pandas中的GroupBy及agg详解

原文:https://www.cnblogs.com/treasury-manager/p/14474963.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!