数据聚合与分组运算

数据聚合与分组运算

分组与聚合的原理

  • 分组:使用特定的条件将原数据划分为多个组
  • 聚合:对每个分组中的数据执行某些操作(如聚合、转换等),最后将计算的结果进行整合
  • 分组和聚合的步骤分为三步:
    1. 拆分:将数据集按照一些标准拆分成若干个组,拆分操作是在指定轴上进行的,既可以对横轴方向上的数据进行分组,也可以对纵轴上的数据进行分组
    1. 应用:将某个函数或方法应用到每个分组
    1. 合并:将产生的新值整合到结果对象中

通过gropby()方法将数据拆分成组

  • df1.groupby(
    by=None,
    axis=0,
    level=None,
    as_index=True,
    sort=True,
    group_keys=True,
    squeeze=False,
    observed=False,
    **kwargs,
    )
  1. by=None:用于确定分组的依据
  2. axis:表示分组的轴的方向,可以为0或1,默认为0
  3. level:如果某个轴是一个MultiIndex对象,则会按照特定级别或多个级别分组
  4. as_index:表示聚合后的数据是否以组标签作为索引的DataFrame对象输出,接受布尔值,默认为True
  5. sort:表示是否对分组标签进行排序,接受布尔值,默认为True
  • by参数接收的数据,也就是常见的分组方式有以下四种:
  • 列表或数组,其长度必须与待分组的轴一样
  • DataFrame对象中某列的名称
  • 字典或者series对象,给出待分组轴上的值与分组名称之间的对应关系
  • 函数,用于处理轴索引或索引中的各个标签

通过列名进行分组

  • 在pandas对象中,如果他的某一列数据满足不同的划分标准,则可以将该列当作分组键来拆分数据集。
df1 = pd.DataFrame({'KEY':['C','B','C','A','B','B','A','C','A'],
                   'DATA':[2,4,6,8,10,1,14,16,18]})
df1
KEY	DATA
0	C	2
1	B	4
2	C	6
3	A	8
4	B	10
5	B	1
6	A	14
7	C	16
8	A	18
gp = df1.groupby(by='KEY') #通过KEY进行分组
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x00000296D65FEB08> 
for i in gp:     # 通过groupby分组后的数据是DataFrameGroupBy类型,需要遍历
    print(i)
('A',   KEY  DATA
3   A     8
6   A    14
8   A    18)
('B',   KEY  DATA
1   B     4
4   B    10
5   B     1)
('C',   KEY  DATA
0   C     2
2   C     6
7   C    16)

通过Series对象进行分组

  • 当被拆分的对象没有相同列名时可以进行拆分可以创建一个series对象充当列名进行拆分
df = pd.DataFrame({'key1':['A','A','B','B','A'],         #创建DF对象
                 'key2':['one','two','one','two','one'],
                   'data1':[2,3,4,6,8],
                   'data2':[3,5,6,3,7]})
df
key1	key2	data1	data2
0	A	one	2	3
1	A	two	3	5
2	B	one	4	6
3	B	two	6	3
4	A	one	8	7

se = pd.Series(['a','b','c','a','b'])        #创建Series对象
se
0    a
1    b
2    c
3    a
4    b
dtype: object

droup_obj = df.groupby(by=se)          #通过by传入Series对象
for i in droup_obj:
    print(i)
('a',   key1 key2  data1  data2
0    A  one      2      3
3    B  two      6      3)
('b',   key1 key2  data1  data2
1    A  two      3      5
4    A  one      8      7)
('c',   key1 key2  data1  data2
2    B  one      4      6)

通过字典进行分组

  • 字典中的键名为自定义分组的列名,值为自定义分组名
num_df = pd.DataFrame({'a':[1,2,3,4,5],
'b':[6,7,8,9,10],
'c':[11,12,13,14,15],
'd':[5,4,3,2,1],
'e':[10,9,8,7,6]})
num_df
mapping = {'a':'第一组','b':'第二组','c':'第一组','d':'第三组','e':'第二组'}
mapping
{'a': '第一组', 'b': '第二组', 'c': '第一组', 'd': '第三组', 'e': '第二组'}

df_gr = num_df.groupby(by=mapping,axis=1)
for i in df_gr:
    print(i)
('第一组',    a   c
0  1  11
1  2  12
2  3  13
3  4  14
4  5  15)
('第三组',    d
0  5
1  4
2  3
3  2
4  1)
('第二组',     b   e
0   6  10
1   7   9
2   8   8
3   9   7
4  10   6)

通过函数进行分组

  • 函数返回的结果为自定义分组的组名,列索引为原数据的列索引
df = pd.DataFrame({'a':[1,2,3,4,5],
                 'b':[6,7,8,9,10],
                 'c':[5,4,3,2,1]},
                 index=['sun','jack','alice','helen','job'])
df

        a	b	c
sun	    1	6	5
jack	2	7	4
alice	3	8	3
helen	4	9	2
job	5	10	1
df_g = df.groupby(len)
i
for i in df_g:
    print(i)
(3,      a   b  c
    sun  1   6  5
    job  5  10  1)
(4,       a  b  c
    jack  2  7  4)
(5,        a  b  c
    alice  3  8  3
    helen  4  9  2)

数据聚合

使用内置统计方法聚合数据

  • 使用内置方法应用到每个分组中,并进算出平均数,最后将每个分组的计算结果合并到一起
import numpy as np
df = pd.DataFrame({'key1':['A','A','B','B','A'],
                    'key2':['ONE','TWO','ONE','TWO','ONE'],
                           'data1':[2,3,4,6,8],
                           'data2':[3,5,np.nan,3,7]})
df
key1	key2	data1	data2
0	A	ONE	2	3.0
1	A	TWO	3	5.0
2	B	ONE	4	NaN
3	B	TWO	6	3.0
4	A	ONE	8	7.0
i
for i in df.groupby('key1'):
    print(i)
('A',   key1 key2  data1  data2
0    A  ONE      2    3.0
1    A  TWO      3    5.0
4    A  ONE      8    7.0)
('B',   key1 key2  data1  data2
2    B  ONE      4    NaN
3    B  TWO      6    3.0)
df.groupby('key1').mean()
data1	data2
key1		
A	4.333333	5.0
B	5.000000	3.0

面向列的聚合方法

  • 当内置方法无法满足聚合要求时,这时可以自定义一个函数,将他传给agg()方法,实现对Series或DataFrame对象进行聚合运算。
  • df.agg(func, axis=0, *args, **kwargs)
  1. func:表示用于汇总数据的函数,可以为单个函数或者函数列表
  2. axis:表示函数作用于轴的方向,0或index表示将函数应用到每一列,1或columns表示将函数应用到每一行,该参数默认为值为0
  • 对每一列数据应用同一个函数
data_frame = pd.DataFrame(np.arange(36).reshape((6,6)),columns=list('abcdef'))
print(data_frame)
a   b   c   d   e   f
0   0   1   2   3   4   5
1   6   7   8   9  10  11
2  12  13  14  15  16  17
3  18  19  20  21  22  23
4  24  25  26  27  28  29
5  30  31  32  33  34  35
data_frame['key'] = pd.Series(list('aaabbb'),name='key')
data_frame

a	b	c	d	e	f	key
0	0	1	2	3	4	5	a
1	6	7	8	9	10	11	a
2	12	13	14	15	16	17	a
3	18	19	20	21	22	23	b
4	24	25	26	27	28	29	b
5	30	31	32	33	34	35	b
_gr = 
data_frame_gr = data_frame.groupby(by = 'key')
dict(x for x in data_frame_gr)['a']
dict(x for x in data_frame_gr)['a']
a	b	c	d	e	f	key
0	0	1	2	3	4	5	a
1	6	7	8	9	10	11	a
2	12	13	14	15	16	17	a
dict(x for x in data_frame_gr)['b']
a	b	c	d	e	f	key
3	18	19	20	21	22	23	b
4	24	25	26	27	28	29	b
5	30	31	32	33	34	35	b
data_frame_gr.agg(sum)
a	b	c	d	e	f
key						
a	18	21	24	27	30	33
b	72	75	78	81	84	87
  • 对某列数据应用到不同的函数
def range_data_group(arr):
    return arr.max()-arr.min()
data_frame_gr.agg([('极差',range_data_group),('和',sum)])
a	b	c	d	e	f
极差	和	极差	和	极差	和	极差	和	极差	和	极差	和
key												
a	12	18	12	21	12	24	12	27	12	30	12	33
b	12	72	12	75	12	78	12	81	12	84	12	87
  • 对不同列应用不同函数
data_frame_gr.agg({'a':'sum','b':'mean','c':range_data_group})
    a	b	c
key			
a	18	7	12
b	72	25	12

分组级运算

数据转换

  • 之前使用agg()方法进行聚合运算时,返回的数据集的形状与被分组数据集的形状是不同的,如果希望保持与原数据集形状相同,那么可以使用transfrom()方法实现,transfrom()方法的语法格式如下:
  • transform(func,*args,**kwargs)
  1. func:表示操作pandas对象的函数,transform方法返回的结果有两种,一种是可以广播的标量值,另一种是与分组大小相同的结果数值。通过本方法操作分组时,会把函数应用到各个分组中,并且将结果返回到适当时位置上
df = pd.DataFrame({'a':[0,1,6,10,3],
                  'b':[1,2,7,11,4],
                  'c':[2,3,8,12,4],
                  'd':[3,4,9,13,5],
                  'e':[4,5,10,14,3],
                  'key':['A','A','B','B','B']})
df
    a	b	c	d	e	key
0	0	1	2	3	4	A
1	1	2	3	4	5	A
2	6	7	8	9	10	B
3	10	11	12	13	14	B
4	3	4	4	5	3	B

data_group = df.groupby('key').transform('mean')#分组求平均数
data_group
        a	        b	    c	d	e
0	0.500000	1.500000	2.5	3.5	4.5
1	0.500000	1.500000	2.5	3.5	4.5
2	6.333333	7.333333	8.0	9.0	9.0
3	6.333333	7.333333	8.0	9.0	9.0
4	6.333333	7.333333	8.0	9.0	9.0
 
df = pd.DataFrame({'A':[2,3,3,4,2],
                  'B':[4,2,3,6,6],
                  'C':[9,7,0,7,8],
                  'D':[3,4,8,6,10]})
df
 
A	B	C	D
0	2	4	9	3
1	3	2	7	4
2	3	3	0	8
3	4	6	7	6
4	2	6	8	10
key = ['one','one','two','two','two']  #传入key,使用key分组
df.groupby(key).transform('mean')
A	B	C	D
0	2.5	3	8	3.5
1	2.5	3	8	3.5
2	3.0	5	5	8.0
3	3.0	5	5	8.0
4	3.0	5	5	8.0

##数据应用
*当有些分组操作,既不适合agg(),也不适合transform()方法,便可以使用apply()方法进行分组操做,它可以作用在每一行,每一列元素上,还可以在许多标准用例中替代聚合和转换

  • apply(func,broadcast=None,raw=False,reduce=None,resul_type=None,args=(),**kwds)
  1. func:表示应用于某一行或某一列的函数
  2. axis:表示函数操作的轴向,'0’或’index’表示作用在列上,'1’或’columns’表示将函数应用于行上,默认为0
  3. broadcast:表示是否将数据进行广播,若设置为False或None,则会返回一个Series对象,其长度跟索引的长度或列数一样,若设置为True,则表示结果将被广播到原始对象中,原始的索引和列将被会保留
df = pd.DataFrame({'data1':[80,23,25,63,94,92,99,92,82,99],
                  'data2':[41,87,58,68,72,89,60,42,53,65],
                  'data3':[30,78,23,66,16,59,20,23,24,40],
                  'key':['b','a','a','b','b','a','b','a','a','a']})
df
data1	data2	data3	key
0	80	41	30	b
1	23	87	78	a
2	25	58	23	a
3	63	68	66	b
4	94	72	16	b
5	92	89	59	a
6	99	60	20	b
7	92	42	23	a
8	82	53	24	a
9	99	65	40	a


df_gr = df.groupby(by='key')  #通过key分组
dict([x for x in df_gr])['b']  #将分组后的数据显现出来
data1	data2	data3	key
0	80	41	30	b
3	63	68	66	b
4	94	72	16	b
6	99	60	20	b


def add_10(arr):           #创建元素加10的函数
    return arr.iloc[:,:3]+10
df_gr.apply(add_10)          #通过apply函数对所有元素进行+10处理
data1	data2	data3
0	90	51	40
1	33	97	88
2	35	68	33
3	73	78	76
4	104	82	26
5	102	99	69
6	109	70	30
7	102	52	33
8	92	63	34
9	109	75	50
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ashan927

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值