Pandas函數(shù)的核心功能是,既計算了統(tǒng)計值,又保留了明細數(shù)據(jù)。為了更好地理解transform和agg的不同,下面從實際的應(yīng)用場景出發(fā)進行對比。
aggregation會返回數(shù)據(jù)的縮減版本,而transformation能返回完整數(shù)據(jù)的某一變換版本供我們重組。這樣的transformation,輸出的形狀和輸入一致。一個常見的例子是通過減去分組平均值來居中數(shù)據(jù)。
#數(shù)據(jù)構(gòu)造
data = pd.DataFrame(
{"company":['百度', '阿里', '百度', '阿里', '百度', '騰訊', '騰訊', '阿里', '騰訊', '阿里'],
"salary":[43000, 24000, 40000, 39000, 8000, 47000, 25000, 16000, 21000, 38000],
"age":[25, 34, 49, 42, 28, 23, 45, 21, 34, 29]})
data
company salary age
0 百度 43000 25
1 阿里 24000 34
2 百度 40000 49
3 阿里 39000 42
4 百度 8000 28
5 騰訊 47000 23
6 騰訊 25000 45
7 阿里 16000 21
8 騰訊 21000 34
9 阿里 38000 29
1、transform作用于Series
1)單個變換函數(shù)
當transform作用于單列Series時較為簡單 ,對salary列進行transform變換我們可以傳入任意的非聚合類函數(shù),比如對工資列對數(shù)化
import pandas as pd
import numpy as np
# 對工資對數(shù)化
data['salary'].transform(np.log)
0 10.668955
1 10.085809
2 10.596635
3 10.571317
4 8.987197
5 10.757903
6 10.126631
7 9.680344
8 9.952278
9 10.545341
Name: salary, dtype: float64
除了內(nèi)置函數(shù),還可以傳入lambda函數(shù)
# lambda函數(shù)
data['salary'].transform(lambda s: s+1)
0 43001
1 24001
2 40001
3 39001
4 8001
5 47001
6 25001
7 16001
8 21001
9 38001
Name: salary, dtype: int64
2)多個變換函數(shù)
也可以傳入包含多個變換函數(shù)的列表來一口氣計算出多列結(jié)果:
data['salary'].transform([np.log, lambda s: s+1, np.sqrt])
log lambda> sqrt
0 10.668955 43001 207.364414
1 10.085809 24001 154.919334
2 10.596635 40001 200.000000
3 10.571317 39001 197.484177
4 8.987197 8001 89.442719
5 10.757903 47001 216.794834
6 10.126631 25001 158.113883
7 9.680344 16001 126.491106
8 9.952278 21001 144.913767
9 10.545341 38001 194.935887
而又因為transform傳入的函數(shù),在執(zhí)行運算時接收的輸入?yún)?shù)是對應(yīng)的整列數(shù)據(jù),所以我們可以利用這個特點實現(xiàn)諸如數(shù)據(jù)標準化、歸一化等需要依賴樣本整體統(tǒng)計特征的變換過程:
# 利用transform進行數(shù)據(jù)標準化
data['salary'].transform(lambda s: (s - s.mean()) / s.std())
0 0.991038
1 -0.468630
2 0.760564
3 0.683739
4 -1.697825
5 1.298337
6 -0.391806
7 -1.083228
8 -0.699104
9 0.606915
Name: salary, dtype: float64
2、 transform作用于DataFrame
當transform作用于整個DataFrame時,實際上就是將傳入的所有變換函數(shù)作用到每一列中:
data.loc[:,'salary':'age'].transform(lambda s:(s-s.mean()) /s.std())
salary age
0 0.991038 -0.832050
1 -0.468630 0.104006
2 0.760564 1.664101
3 0.683739 0.936057
4 -1.697825 -0.520031
5 1.298337 -1.040063
6 -0.391806 1.248075
7 -1.083228 -1.248075
8 -0.699104 0.104006
9 0.606915 -0.416025
而當傳入多個變換函數(shù)時,對應(yīng)的返回結(jié)果格式類似agg中的機制,會生成MultiIndex格式的字段名
data.loc[:, 'salary': 'age'].transform([np.log, lambda s: s+1])
salary age
log lambda> log lambda>
0 10.668955 43001 3.218876 26
1 10.085809 24001 3.526361 35
2 10.596635 40001 3.891820 50
3 10.571317 39001 3.737670 43
4 8.987197 8001 3.332205 29
5 10.757903 47001 3.135494 24
6 10.126631 25001 3.806662 46
7 9.680344 16001 3.044522 22
8 9.952278 21001 3.526361 35
9 10.545341 38001 3.367296 30
而且由于作用的是DataFrame,還可以利用字典以鍵值對的形式,一口氣為每一列配置單個或多個變換函數(shù):
(data.loc[:, 'salary': 'age']
.transform({'age': lambda s: (s - s.mean()) / s.std(),
'salary': [np.log, np.sqrt]}))
age salary
lambda> log sqrt
0 -0.832050 10.668955 207.364414
1 0.104006 10.085809 154.919334
2 1.664101 10.596635 200.000000
3 0.936057 10.571317 197.484177
4 -0.520031 8.987197 89.442719
5 -1.040063 10.757903 216.794834
6 1.248075 10.126631 158.113883
7 -1.248075 9.680344 126.491106
8 0.104006 9.952278 144.913767
9 -0.416025 10.545341 194.935887
3、transform作用于groupby分組后
在原來的數(shù)據(jù)中,我們知道了如何求不同公司的平均薪水,假如需要在原數(shù)據(jù)集中新增一列salary_mean,代表該公司的平均薪水,該怎么實現(xiàn)呢?
data['salary_mean'] = data.groupby('company')[['salary']].transform('mean')
data
company salary age salary_mean
0 百度 43000 25 30333.333333
1 阿里 24000 34 29250.000000
2 百度 40000 49 30333.333333
3 阿里 39000 42 29250.000000
4 百度 8000 28 30333.333333
5 騰訊 47000 23 31000.000000
6 騰訊 25000 45 31000.000000
7 阿里 16000 21 29250.000000
8 騰訊 21000 34 31000.000000
9 阿里 38000 29 29250.000000
通過上面的數(shù)據(jù)可以看出,利用transform輸出既得到了統(tǒng)計數(shù)據(jù),形狀也沒有變化。
當然,也可對多個數(shù)據(jù)列進行計算
data.groupby('company')[['salary', 'age']].transform('mean')
salary age
0 30333.333333 34.0
1 29250.000000 31.5
2 30333.333333 34.0
3 29250.000000 31.5
4 30333.333333 34.0
5 31000.000000 34.0
6 31000.000000 34.0
7 29250.000000 31.5
8 31000.000000 34.0
9 29250.000000 31.5
我們也可以用map函數(shù)實現(xiàn)類似的功能,但是稍微復(fù)雜點,但是有助于我們理解transform的含義。
avg_dict = data.groupby('company')['salary'].mean().to_dict()
avg_dict#得到了一個平均工資的字典
{'百度': 30333.333333333332, '騰訊': 31000.0, '阿里': 29250.0}
#利用map函數(shù),將得到的字典映射到對應(yīng)的列
data['salary_mean'] = data['company'].map(avg_dict)
data
company salary age salary_mean
0 百度 43000 25 30333.333333
1 阿里 24000 34 29250.000000
2 百度 40000 49 30333.333333
3 阿里 39000 42 29250.000000
4 百度 8000 28 30333.333333
5 騰訊 47000 23 31000.000000
6 騰訊 25000 45 31000.000000
7 阿里 16000 21 29250.000000
8 騰訊 21000 34 31000.000000
9 阿里 38000 29 29250.000000
以圖解的方式來看看進行g(shù)roupby后transform的實現(xiàn)過程(公司列包含ABC,salary列為每個員工的工資明細):
上圖中的大方框是transform和agg 所不一樣的地方,對agg而言,會計算并聚合得到 A,B,C 公司對應(yīng)的均值并直接返回,每個公司一條數(shù)據(jù),但對transform而言,則會對每一條數(shù)據(jù)求得相應(yīng)的結(jié)果,同一組內(nèi)的樣本會有相同的值,組內(nèi)求完均值后會按照原索引的順序返回結(jié)果。
以上就是分享Pandas中的一些寶藏函數(shù)transform()的詳細內(nèi)容,更多關(guān)于Pandas函數(shù)transform()的資料請關(guān)注腳本之家其它相關(guān)文章!
您可能感興趣的文章:- pandas數(shù)據(jù)分組groupby()和統(tǒng)計函數(shù)agg()的使用
- pandas之分組groupby()的使用整理與總結(jié)
- Pandas中的 transform()結(jié)合 groupby()用法示例詳解