Pandas tricks 之 transform的用法
點擊上方“超哥的雜貨鋪”,輕松關(guān)注

先來看一個實例問題。
如下銷售數(shù)據(jù)中展現(xiàn)了三筆訂單,每筆訂單買了多種商品,求每種商品銷售額占該筆訂單總金額的比例。例如第一條數(shù)據(jù)的最終結(jié)果為:235.83 / (235.83+232.32+107.97) = 40.93%。
后臺回復(fù)“transform”獲取本文全部代碼和pdf版本。
思路一:
常規(guī)的解法是,先用對訂單id分組,求出每筆訂單的總金額,再將源數(shù)據(jù)和得到的總金額進(jìn)行“關(guān)聯(lián)”。最后把相應(yīng)的兩列相除即可。相應(yīng)的代碼如下:
1.對訂單id分組,求每筆訂單總額。由于有三個order,因此最終會產(chǎn)生三條記錄表示三個總金額。

2.數(shù)據(jù)關(guān)聯(lián)合并

為了使每行都出現(xiàn)相應(yīng)order的總金額,需要使用“左關(guān)聯(lián)”。我們使用源數(shù)據(jù)在左,聚合后的總金額數(shù)據(jù)在右(反過來也可)。不指定連接key,則會自動查找相應(yīng)的關(guān)聯(lián)字段。由于是多行對一行的關(guān)聯(lián),關(guān)聯(lián)上的就會將總金額重復(fù)顯示多次,剛好符合我們后面計算的需要。結(jié)果如上圖所示。
3.計算占比
有了前面的基礎(chǔ),就可以進(jìn)行最終計算了:直接用商品金額ext_price除以訂單總額sum_price。并賦值給新的列pct即可。

4.格式調(diào)整
為了美觀,可以將小數(shù)形式轉(zhuǎn)換為百分比形式,自定義函數(shù)即可實現(xiàn)。

思路二:
對于上面的過程,pandas中的transform函數(shù)提供了更簡潔的實現(xiàn)方式,如下所示:

可以看到,這種方法把前面的第一步和第二步合成了一步,直接得到了sum_price列。這就是transform的核心:作用于groupby之后的每個組的所有數(shù)據(jù)??梢詤⒖枷旅娴氖疽鈭D幫助理解:

后面的步驟和前面一致。

這種方法在需要對多列分組的時候同樣適用。
多列分組使用transform
為演示效果,我們虛構(gòu)了如下數(shù)據(jù),id,name,cls為維度列。

我們想求:以(id,name,cls)為分組,每組stu的數(shù)量占各組總stu的比例。使用transform處理如下:

同樣再次計算占比和格式化,得到最終結(jié)果:

總結(jié)transform的用法
transform函數(shù)的官方文檔簽名為:DataFrame.transform(func,axis=0,*args,**kwargs),表示調(diào)用func函數(shù)進(jìn)行轉(zhuǎn)換,返回轉(zhuǎn)換后的值,且返回值與原來的數(shù)據(jù)在相同的軸上具有相同的長度。func可以是函數(shù),字符串,列表或字典。具體可以參考官方文檔:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.transform.html#pandas.DataFrame.transform。
transform既可以和groupby一起使用,也可以單獨使用。
1.單獨使用
此時,在某些情況下可以實現(xiàn)和apply函數(shù)類似的結(jié)果。


2.與groupby一起使用
此時,transform函數(shù)返回與原數(shù)據(jù)一樣數(shù)量的行,并將函數(shù)的結(jié)果分配回原始的dataframe。也就是說返回的shape是(len(df),1)。本文開頭的例子就是這樣。而apply函數(shù)返回聚合后的行數(shù)。例如:

transform和apply的另一個區(qū)別是,apply函數(shù)可以同時作用于多列,而transform不可以。下面用例子說明:

上圖中的例子,定義了處理兩列差的函數(shù),在groupby之后分別調(diào)用apply和transform,transform并不能執(zhí)行。如果不采用groupby,直接調(diào)用,也會有問題,參見下面的第二種調(diào)用方式。

第三種調(diào)用調(diào)用方式修改了函數(shù),transform依然不能執(zhí)行。以上三種調(diào)用apply的方式處理兩列的差,換成transform都會報錯。
利用transform填充缺失值
transform另一個比較突出的作用是用于填充缺失值。舉例如下:

在上面的示例數(shù)據(jù)中,按照name可以分為三組,每組都有缺失值。用平均值填充是一種處理缺失值常見的方式。此處我們可以使用transform對每一組按照組內(nèi)的平均值填充缺失值。

小結(jié):
transform函數(shù)經(jīng)常與groupby一起使用,并將返回的數(shù)據(jù)重新分配到每個組去。利用這一點可以方便求占比和填充缺失值。但需要注意,相比于apply,它的局限在于只能處理單列的數(shù)據(jù)。
后臺回復(fù)“transform”獲取本文全部代碼和pdf版本。
Reference:
https://www.codenong.com/19966018/
https://www.cnblogs.com/junge-mike/p/12761227.html
https://blog.csdn.net/qq_40587575/article/details/81204514
https://pbpython.com/pandas_transform.html
以清凈心看世界;
用歡喜心過生活。
超哥的雜貨鋪,你值得擁有~
長按二維碼關(guān)注我們
推薦閱讀
不再糾結(jié),一文詳解pandas中的map、apply、applymap、groupby、agg...
