将自己定义的或其他库的函数应用于Pandas对象,有以下3种方法:
- apply():逐行或逐列应用该函数
- agg()和transform():聚合和转换
- applymap():逐元素应用函数
一 、apply()
其中:设置axis = 1参数,可以逐行进行操作;默认axis=0,即逐列进行操作;
对于常见的描述性统计方法,可以直接使用一个字符串进行代替,例df.apply('mean')等价于df.apply(np.mean);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
>>> 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))
<
class
'pandas.core.series.Series'
>
>>> df[
'score_math'
].
apply
(
'mean'
)
86.33333333333333
>>>
type
(df[
'score_math'
].
apply
(np.mean))
<
class
'pandas.core.series.Series'
>
#逐行求每个学生的平均分
>>> 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
))
<
class
'pandas.core.series.Series'
>
|
apply()的返回结果与所用的函数是相关的:
- 返回结果是Series对象:如上述例子应用的均值函数,就是每一行或每一列返回一个值;
- 返回大小相同的DataFrame:如下面自定的lambda函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#其中的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
))
<
class
'pandas.core.frame.DataFrame'
>
|
二、数据聚合agg()
- 数据聚合agg()指任何能够从数组产生标量值的过程;
- 相当于apply()的特例,可以对pandas对象进行逐行或逐列的处理;
- 能使用agg()的地方,基本上都可以使用apply()代替。
例:
1)对两门课逐列求平均分
1
2
3
4
5
6
7
8
|
>>> 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)应用多个函数,可将函数放于一个列表中;
例:对两门课分别求最高分与最低分
1
2
3
4
5
6
7
8
|
>>> 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)使用字典可以对特定列应用特定及多个函数;
例:对数学成绩求均值和最小值,对音乐课求最大值
1
2
3
4
5
|
>>> 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)将报错,转换是无法产生聚合结果的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#将成绩减去各课程的平均分,使用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,返回结果中:
- 在列索引上第一级别是原始列名
- 在第二级别上是转换的函数名
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> df.transform([
lambda
x:x
-
x.mean(),
lambda
x:x
/
10
])
score_math score_music
<
lambda
> <
lambda
> <
lambda
> <
lambda
>
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的实例方法
例:对成绩保留小数后两位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
>>> 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,但标量会被广播。