在pandas中使用pipe()提升代碼可讀性
1. 簡(jiǎn)介
我們?cè)诶胮andas開(kāi)展數(shù)據(jù)分析時(shí),應(yīng)盡量避免過(guò)于「碎片化」的組織代碼,尤其是創(chuàng)建出過(guò)多不必要的「中間變量」,既浪費(fèi)了「內(nèi)存」,又帶來(lái)了關(guān)于變量命名的麻煩,更不利于整體分析過(guò)程代碼的可讀性,因此以流水線方式組織代碼非常有必要。
圖1
而在以前我撰寫(xiě)的一些文章中,為大家介紹過(guò)pandas中的eval()和query()這兩個(gè)幫助我們鏈?zhǔn)綍?shū)寫(xiě)代碼,搭建數(shù)據(jù)分析工作流的實(shí)用API,再加上下面要介紹的pipe(),我們就可以將任意pandas代碼完美組織成流水線形式。
2. 在pandas中靈活利用pipe()pipe()
顧名思義,就是專(zhuān)門(mén)用于對(duì)Series和DataFrame操作進(jìn)行流水線(pipeline)改造的API,其作用是將嵌套的函數(shù)調(diào)用過(guò)程改造為「鏈?zhǔn)健惯^(guò)程,其第一個(gè)參數(shù)func傳入作用于對(duì)應(yīng)Series或DataFrame的函數(shù)。
具體來(lái)說(shuō)pipe()有兩種使用方式,「第一種方式」下,傳入函數(shù)對(duì)應(yīng)的第一個(gè)位置上的參數(shù)必須是目標(biāo)Series或DataFrame,其他相關(guān)的參數(shù)使用常規(guī)的「鍵值對(duì)」方式傳入即可,就像下面的例子一樣,我們自編函數(shù)對(duì)「泰坦尼克數(shù)據(jù)集」進(jìn)行一些基礎(chǔ)的特征工程處理:
- import pandas as pd
- train = pd.read_csv('train.csv')
- def do_something(data, dummy_columns):
- '''
- 自編示例函數(shù)
- '''
- data = (
- pd
- # 對(duì)指定列生成啞變量
- .get_dummies(data, # 先刪除data中指定列
- columns=dummy_columns,
- drop_first=True)
- )
- return data
- # 鏈?zhǔn)搅魉€
- (
- train
- # 將Pclass列轉(zhuǎn)換為字符型以便之后的啞變量處理
- .eval('PclassPclass=Pclass.astype("str")', engine='python')
- # 刪除指定列
- .drop(columns=['PassengerId', 'Name', 'Cabin', 'Ticket'])
- # 利用pipe以鏈?zhǔn)降姆绞秸{(diào)用自編函數(shù)
- .pipe(do_something,
- dummy_columns=['Pclass', 'Sex', 'Embarked'])
- # 刪除含有缺失值的行
- .dropna()
- )
可以看到,在緊接著drop()下一步的pipe()中,我們將自編函數(shù)作為其第一個(gè)參數(shù)傳入,從而將一系列操作巧妙地嵌入到鏈?zhǔn)竭^(guò)程中。
「第二種使用方式」適合目標(biāo)Series和DataFrame不為傳入函數(shù)第一個(gè)參數(shù)的情況,譬如下面的例子中我們假設(shè)目標(biāo)輸入數(shù)據(jù)為第二個(gè)參數(shù)data2,則pipe()的第一個(gè)參數(shù)應(yīng)以(函數(shù)名, '參數(shù)名稱(chēng)')的格式傳入:
- def do_something(data1, data2, axis):
- '''
- 自編示例函數(shù)
- '''
- data = (
- pd
- .concat([data1, data2], axisaxis=axis)
- )
- return data
- # pipe()第二種使用方式
- (
- train
- .pipe((do_something, 'data2'), data1=train, axis=0)
- )
在這樣的設(shè)計(jì)下我們可以避免很多函數(shù)嵌套調(diào)用方式,隨心所欲地優(yōu)化我們的代碼~