首页  > 世界杯女主持人 > Pandas数据分组的函数应用(df.appy()、df.agg()、df.transform()、df.appymap()、df.groupby())

Pandas数据分组的函数应用(df.appy()、df.agg()、df.transform()、df.appymap()、df.groupby())

世界杯女主持人 2025-10-25 05:18:23 6711

apply()数据聚合agg()数据转换transform()applymap()groupby().apply()分组分组 - 可迭代对象其他轴上的分组通过字典或者Series分组通过函数分组分组计算函数方法多函数计算:agg()

将自己定义的或其他库的函数应用于Pandas对象:

apply():逐行或逐列应用该函数 agg()和transform():聚合和转换 applymap():逐元素应用函数 groupby().apply():聚合之后应用于某个函数

apply()

介绍

apply函数是pandas里面所有函数中自由度最高的函数。该函数如下:

DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)

该函数最有用的是第一个参数,这个参数是函数,相当于C/C++的函数指针。

这个函数需要自己实现,函数的传入参数根据axis来定,比如axis = 1,就会把一行数据作为Series的数据 结构传入给自己实现的函数中,我们在函数中实现对Series不同属性之间的计算,返回一个结果,则apply函数 会自动遍历每一行DataFrame的数据,最后将所有结果组合成一个Series数据结构并返回。

样例

import numpy as np

import pandas as pd

if __name__ == '__main__':

f = lambda x : x.max() - x.min()

df = pd.DataFrame(np.random.randn(4,

3), columns=list('bde'), index=['utah', 'ohio', 'texas', 'oregon']) #columns表述列标,

index表述行标

print(df)

t1 = df.apply(f) #df.apply(function,

axis=0),默认axis=0,表示将一列数据作为Series的数据结构传入给定的function中

print(t1)

t2 = df.apply(f, axis=1)

print(t2)

输出结果如下所示:

b d e

utah 1.950737 0.318299

0.387724

ohio 1.584464 -0.082965 0.984757

texas 0.477283 -2.774454 -0.532181

oregon -0.851359 -0.654882 1.026698

b 2.802096

d 3.092753

e 1.558879

dtype: float64

utah 1.632438

ohio 1.667428

texas 3.251737

oregon 1.878057

dtype: float64

性能比较

import numpy as np

import pandas as pd

def my_test(a, b):

return a + b

if __name__ == '__main__':

df =

pd.DataFrame({'a':np.random.randn(6),

'b':['foo', 'bar']

* 3,

'c':np.random.randn(6)})

print(df)

df['value1'] = df.apply(lambda row:

my_test(row['a'], row['c']), axis=1)

print(df)

df['vaule2'] = df['a'] + df['c']

print(df)

输出结果如下:

a b

c

0 -1.745471 foo 0.723341

1 -0.378998 bar 0.229188

2 -1.468866 foo 0.788046

3 -1.323347 bar 0.323051

4 -1.894372 foo 2.216768

5 -0.649059 bar 0.858149

a b

c value1

0 -1.745471 foo 0.723341 -1.022130

1 -0.378998 bar 0.229188 -0.149810

2 -1.468866 foo 0.788046 -0.680820

3 -1.323347 bar 0.323051 -1.000296

4 -1.894372 foo 2.216768

0.322396

5 -0.649059 bar 0.858149

0.209089

a b

c value1 vaule2

0 -1.745471 foo 0.723341 -1.022130 -1.022130

1 -0.378998 bar 0.229188 -0.149810 -0.149810

2 -1.468866 foo 0.788046 -0.680820 -0.680820

3 -1.323347 bar 0.323051 -1.000296 -1.000296

4 -1.894372 foo 2.216768

0.322396 0.322396

5 -0.649059 bar 0.858149

0.209089 0.209089

注意:当数据量很大时,对于简单的逻辑处理建议方法2(个人处理几百M数据集时,方法1花时200s左右,方法2花时10s)

其中:设置axis = 1参数,可以逐行进行操作;默认axis=0,即逐列进行操作;

对于常见的描述性统计方法,可以直接使用一个字符串进行代替,例df.apply(‘mean’)等价于df.apply(np.mean);

>>> df =

pd.read_excel('./input/class.xlsx)

>>> df = df[['score_math','score_music']]

>>> df

score_math score_music

0 95 79

1 96 90

2 85 85

3 93 92

4 84 90

5 88 70

6 59 89

7 88 86

8 89 74

#对音乐课和数学课逐列求成绩平均分

>>> df.apply(np.mean)

score_math 86.333333

score_music 83.888889

dtype: float64

>>> type(df.apply(np.mean))

>>> df['score_math'].apply('mean')

86.33333333333333

>>> type(df['score_math'].apply(np.mean))

#逐行求每个学生的平均分

>>> df.apply(np.mean,axis=1)

0 87.0

1 93.0

2 85.0

3 92.5

4 87.0

5 79.0

6 74.0

7 87.0

8 81.5

dtype: float64

>>> type(df.apply(np.mean,axis=1))

apply()的返回结果与所用的函数是相关的:

返回结果是Series对象:如上述例子应用的均值函数,就是每一行或每一列返回一个值;返回大小相同的DataFrame:如下面自定的lambda函数。

#其中的x可以看作是每一类的Series对象

>>> df.apply(lambda x: x - 5)

score_math score_music

0 90 74

1 91 85

2 80 80

3 88 87

4 79 85

5 83 65

6 54 84

7 83 81

8 84 69

>>> type(df.apply(lambda x: x - 5))

数据聚合agg()

数据聚合agg()指任何能够从数组产生标量值的过程;相当于apply()的特例,可以对pandas对象进行逐行或逐列的处理;能使用agg()的地方,基本上都可以使用apply()代替。

例: 1)对两门课逐列求平均分

>>>

df.agg('mean')

score_math 86.333333

score_music 83.888889

dtype: float64

>>> df.apply('mean')

score_math 86.333333

score_music 83.888889

dtype: float64

2)应用多个函数,可将函数放于一个列表中;

例:对两门课分别求最高分与最低分

>>>

df.agg(['max','min'])

score_math score_music

max 96 92

min 59 70

>>> df.apply([np.max,'min'])

score_math score_music

amax 96 92

min 59 70

3)使用字典可以对特定列应用特定及多个函数;

例:对数学成绩求均值和最小值,对音乐课求最大值

>>>

df.agg({'score_math':['mean','min'],'score_music':'max'})

score_math score_music

max NaN 92.0

mean 86.333333 NaN

min 59.000000 NaN

数据转换transform()

特点:使用一个函数后,返回相同大小的Pandas对象

与数据聚合agg()的区别:

数据聚合agg()返回的是对组内全量数据的缩减过程;数据转换transform()返回的是一个新的全量数据。

注意:df.transform(np.mean)将报错,转换是无法产生聚合结果的

#将成绩减去各课程的平均分,使用apply、agg、transfrom都可以实现

>>> df.transform(lambda x:x-x.mean())

>>> df.apply(lambda x:x-x.mean())

>>> df.agg(lambda x:x-x.mean())

score_math score_music

0 8.666667 -4.888889

1 9.666667 6.111111

2 -1.333333 1.111111

3 6.666667 8.111111

4 -2.333333 6.111111

5 1.666667 -13.888889

6 -27.333333 5.111111

7 1.666667 2.111111

8 2.666667 -9.888889

当应用多个函数时,将返回于原始DataFrame大小不同的DataFrame,返回结果中:

在列索引上第一级别是原始列名在第二级别上是转换的函数名

>>>

df.transform([lambda x:x-x.mean(),lambda x:x/10])

score_math score_music

0 8.666667 9.5

-4.888889 7.9

1 9.666667 9.6

6.111111 9.0

2 -1.333333 8.5

1.111111 8.5

3 6.666667 9.3

8.111111 9.2

4 -2.333333 8.4

6.111111 9.0

5 1.666667 8.8

-13.888889 7.0

6 -27.333333 5.9 5.111111 8.9

7 1.666667 8.8

2.111111 8.6

8 2.666667 8.9

-9.888889 7.4

applymap()

applymap()对pandas对象逐元素应用某个函数,成为元素级函数应用;

与map()的区别:

applymap()是DataFrame的实例方法map()是Series的实例方法

例:对成绩保留小数后两位

>>>

df.applymap(lambda x:'%.2f'%x)

score_math score_music

0 95.00 79.00

1 96.00 90.00

2 85.00 85.00

3 93.00 92.00

4 84.00 90.00

5 88.00 70.00

6 59.00 89.00

7 88.00 86.00

8 89.00 74.00

>>> df['score_math'].map(lambda x:'%.2f'%x)

0 95.00

1 96.00

2 85.00

3 93.00

4 84.00

5 88.00

6 59.00

7 88.00

8 89.00

Name: score_math, dtype: object

从上述例子可以看出,applymap()操作实际上是对每列的Series对象进行了map()操作

通过以上分析我们可以看到,apply、agg、transform三种方法都可以对分组数据进行函数操作,但也各有特色,总结如下:

apply中自定义函数对每个分组数据单独进行处理,再将结果合并;整个DataFrame的函数输出可以是标量、Series或DataFrame;每个apply语句只能传入一个函数;agg可以通过字典方式指定特征进行不同的函数操作,每一特征的函数输出必须为标量;transform不可以通过字典方式指定特征进行不同的函数操作,但函数运算单位也是DataFrame的每一特征,每一特征的函数输出可以是标量或者Series,但标量会被广播。

groupby().apply()

Dataframe在行(axis=0)或列(axis=1)上进行分组,将一个函数应用到各个分组并产生一个新值,然后函数执行结果被合并到最终的结果对象中。

df.groupby(by=None, axis=0, level=None,

as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)

import numpy as np

import pandas as pd

data = pd.DataFrame({'key1':list('aabba'),

'key2':

['one','two','one','two','one'],

'data1': np.random.randn(5),

'data2':

np.random.randn(5)})

def f(group):

group['sum'] = group.data1.sum()

return group

aa = data.groupby(['key1','key2']).apply(f)

print(data)

print('*'*30)

print(aa)

bb = data.groupby(['key1','key2'])['data1'].apply(lambda x:x)

print('*'*30)

print(bb)

cc=data.groupby(['key1','key2']).indices

print('*'*30)

print(cc)

结果

key1 key2

data1 data2

0 a

one -1.065003 0.775987

1 a

two -0.106187 -0.024468

2 b

one 1.079181 -0.499718

3 b

two -0.224642 0.213094

4 a

one 0.771805 1.877397

******************************

key1 key2 data1

data2 sum

0 a

one -1.065003 0.775987 -0.293198

1 a

two -0.106187 -0.024468 -0.106187

2 b

one 1.079181 -0.499718 1.079181

3 b

two -0.224642 0.213094 -0.224642

4 a

one 0.771805 1.877397 -0.293198

******************************

0 -1.065003

1 -0.106187

2 1.079181

3 -0.224642

4 0.771805

Name: data1, dtype: float64

******************************

{('a', 'one'): array([0, 4], dtype=int64),

('a', 'two'): array([1], dtype=int64),

('b', 'one'): array([2], dtype=int64),

('b', 'two'): array([3], dtype=int64)}

分组

df = pd.DataFrame({'A' :

['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],

'B' : ['one', 'one',

'two', 'three', 'two', 'two', 'one', 'three'],

'C' :

np.random.randn(8),

'D' :

np.random.randn(8)})

print(df)

print('------')

print(df.groupby('A'), type(df.groupby('A')))

print('------')

# 直接分组得到一个groupby对象,是一个中间数据,没有进行计算

a = df.groupby('A').mean()

b = df.groupby(['A','B']).mean()

c = df.groupby(['A'])['D'].mean() # 以A分组,算D的平均值

print("-----------------")

print(a,type(a),'\n',a.columns)

print()

print(b,type(b),'\n',b.columns)

print()

print(c,type(c))

# 通过分组后的计算,得到一个新的dataframe

# 默认axis = 0,以行来分组

# 可单个或多个([])列分组

#按A列分组求出A,B列的个数

grouped = df.groupby(["A"])

n = grouped.agg({"A": ["count", pd.Series.unique],

"B": pd.Series.nunique})

print(n)

分组 - 可迭代对象

df = pd.DataFrame({'X' :

['A', 'B', 'A', 'B'], 'Y' : [1, 4, 3, 2]})

print(df)

print(df.groupby('X'), type(df.groupby('X')))

print('-----')

print(list(df.groupby('X')), '→ 可迭代对象,直接生成list\n')

print(list(df.groupby('X'))[0], '→ 以元祖形式显示\n')

for n,g in df.groupby('X'):

print(n)

print(g)

print('###')

print('-----')

# n是组名,g是分组后的Dataframe

print(df.groupby(['X']).get_group('A'),'\n')

print(df.groupby(['X']).get_group('B'),'\n')

print('-----')

# .get_group()提取分组后的组

grouped = df.groupby(['X'])

print(grouped.groups)

print(grouped.groups['A']) # 也可写:df.groupby('X').groups['A']

print('-----')

# .groups:将分组后的groups转为dict

# 可以字典索引方法来查看groups里的元素

sz = grouped.size()

print(sz,type(sz))

print('-----')

# .size():查看分组后的长度

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo',

'foo'],

'B' : ['one', 'one',

'two', 'three', 'two', 'two', 'one', 'three'],

'C' :

np.random.randn(8),

'D' :

np.random.randn(8)})

print(df)

print()

print(df.groupby(['A','B']))

print()

grouped = df.groupby(['A','B']).groups

print(grouped)

print()

print(grouped[('foo', 'three')])

# 按照两个列进行分组

其他轴上的分组

import pandas as pd

import numpy as np

df = pd.DataFrame({'data1':np.random.rand(2),

'data2':np.random.rand(2),

'key1':['a','b'],

'key2':['one','two']})

print(df)

print(df.dtypes)

print("-------------")

print(df.groupby(df.dtypes, axis=1))

print('-----')

print(list(df.groupby(df.dtypes, axis=1)))

print()

for n,p in df.groupby(df.dtypes, axis=1):

print(n)

print()

print(p)

print('##')

# 按照值类型分列

通过字典或者Series分组

df =

pd.DataFrame(np.arange(16).reshape(4,4),

columns =

['a','b','c','d'])

print(df)

print('-----')

mapping = {'a':'one','b':'one','c':'two','d':'two','e':'three'}

by_column = df.groupby(mapping, axis = 1)

print(by_column.sum())

print('-----')

# mapping中,a、b列对应的为one,c、d列对应的为two,以字典来分组

s = pd.Series(mapping)

print(s,'\n')

print(s.groupby(s).count())

# s中,index中a、b对应的为one,c、d对应的为two,以Series来分组

通过函数分组

df =

pd.DataFrame(np.arange(16).reshape(4,4),

columns =

['a','b','c','d'],

index =

['abc','bcd','aa','b'])

print(df,'\n')

print(df.groupby(len).sum())

# 按照字母长度分组

分组计算函数方法

s = pd.Series([1, 2, 3,

10, 20, 30], index = [1, 2, 3, 1, 2, 3])

grouped = s.groupby(level=0) # 唯一索引用.groupby(level=0),将同一个index的分为一组

print(grouped)

print(grouped.first(),'→ first:非NaN的第一个值\n')

print(grouped.last(),'→ last:非NaN的最后一个值\n')

print(grouped.sum(),'→ sum:非NaN的和\n')

print(grouped.mean(),'→ mean:非NaN的平均值\n')

print(grouped.median(),'→ median:非NaN的算术中位数\n')

print(grouped.count(),'→ count:非NaN的值\n')

print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')

print(grouped.std(),'→ std,var:非NaN的标准差和方差\n')

print(grouped.prod(),'→ prod:非NaN的积\n')

print(grouped.size()) # 获取分组后每组的数量

多函数计算:agg()

df =

pd.DataFrame({'a':[1,1,2,2],

'b':np.random.rand(4),

'c':np.random.rand(4),

'd':np.random.rand(4),})

print(df)

print(df.groupby('a').agg(['mean',np.sum]))

print(df.groupby('a')['b'].agg({'result1':np.mean,

'result2':np.sum}))

# 函数写法可以用str,或者np.方法

# 可以通过list,dict传入,当用dict时,key名为columns

参考:https://www.cnblogs.com/Cheryol/p/13451562.html

https://www.cnblogs.com/mliu222/p/12003794.html

https://blog.csdn.net/spiral1221/article/details/76152002

https://www.cnblogs.com/feifeifeisir/p/13792217.html


友情链接:
Copyright © 2015 冲击世界杯_2002韩日世界杯 - 0534pos.com All Rights Reserved.