將自己定義的或其他庫的函數應用於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,但標量會被廣播。
