作者 | 周志鵬
責編 | 劉靜
這是Python數據分析實戰基礎的第四篇內容,也是基礎系列的最後一篇,接下來就進入實戰系列了。本文主要講的是Pandas中第二好用的函數——apply。
為什麼說第二好用呢?做人嘛,最重要的就是謙虛,做函數也是一樣的,而apply就是這樣一個優雅而謙虛的函數。
我們單獨用一篇來為apply樹碑立傳,原因有二,一是因為apply函數極其靈活高效,甚至是重新定義了pandas的靈活,一旦熟練運用,在數據清洗和分析界可謂是「屠龍在手,天下我有」;二是apply概念相對晦澀,需要結合具體案例去咀嚼和實踐。
Apply初體驗
apply函數,因為她總是和分組函數一起出現,所以在江湖得了個「groupby伴侶」的稱號。她的主要作用是做聚合運算,以及在分組基礎上根據實際情況來自定義一些規則,常見用法和參數如下:
如果把源數據比作麵粉,groupby分組就是把麵粉揉成一個個麵團的過程,apply起到的作用,是根據數據需求來調餡,並且把每一個麵團包成我們喜歡的包子。接下來,我們通過兩個場景,更深入的感受下apply函數的優雅迷人。
場景一
背景:我們拿到了一份4位同學三次模擬考試的成績,想知道每位同學歷次模擬中最好成績和最差成績分別是多少。
思路:最好和最差,分別對應著max與min,我們先按姓名分組,再用apply函數返回對應的最大和最小值,最終將結果合併。
先導入源數據:
看一看每位同學最高成績:
我們指定「綜合成績」列,然後把max函數直接傳入apply參數內,返回了對應分組內成績的最大值。有一些常見函數,如max、min、len等函數可以直接傳入apply。
groupby分組默認會把分組依據列(姓名)變成索引,這裡用reset_index方法重置或者說取消姓名索引,將它保留在列的位置,維持DataFrame格式,方便後續匹配。
再篩選出最低成績:
兩張表按姓名合併:
得到了我們預期的結果,只是列名略醜,可以用.columns方法來賦值更改。場景一比較死板和嚴肅,場景二我們換個更接地氣的風格。
場景二
背景:Boss丟過來一份省市銷售表,裡面包含省份、城市、最近1個月銷售額3個欄位,沒等你開口問需求,Boss就開腔了:「小Z啊,我最近對3這個數字有執念,我想看看每個省份銷售排名第3的都是哪些城市,以及他們的銷售額情況。對了,這個需求要儘快!」
思路:問題的關鍵是找到每個省份銷售排名第3的城市,首先,應該對省份、城市按銷售額進行降序排列,然後,找到對應排名第3的城市,Emmm,如果是排名第1的城市,我們可以通過排序後去重實現,但是這個排名第3,小Z瘋狂撓頭,還是沒有什麼思路。
於是弱弱的請求寬限時間:「領導,我覺得這個需求可能要花多一些時間,因為...」
「我不要你覺得!我要我覺得!現在是17:00,我覺得半個小時時間已經夠充裕了!」Boss放下了手中的《明學是怎樣煉成的》,語氣斬釘截鐵又毋庸置疑。
小Z在無奈和絕望之中,想起了那句詩「假如數據清洗難住了你,不要悲傷,不要心急,憂鬱的日子裡需要apply」,一瞬間通透了。
說幹就幹,先導入數據源,對數據做個初步了解:
數據源有省份、城市、近1月銷售額3個欄位,一共210行(銷售額)亂序排列,且都沒有空值,整體比較規整。
要得到銷售排名第3的城市,要先進行排序,這裡我們用省份、近1月銷售額兩個關鍵欄位進行降序排列,得到我們期待的順序:
接著,在apply函數登場前,我們先詳細剖析一下整個過程:
apply的精髓,在於揉面和DIY(調餡)包子。我們需要把源數據(麵粉)給揉成一個個麵團,再把一個個麵團DIY成我們想要口味的包子。其中,揉面的過程就是groupby分組,而DIY調餡做包子就是apply自定義函數和應用的過程。
結合我們的目標,揉面是按省份進行分組,得到每個省各個城市和對應銷售額的麵團;DIY包子是在每個麵團中取其第三名的城市和銷售額欄位。
第一步分組非常簡單,按省份分組即可。而取第3名的城市和銷售,表明我們需要城市和銷售兩個欄位,所以在分組後指明這兩列:
這一步,我們已經揉好了面,原始的麵團也初步成型,雖然返回的結果有點晦澀,但是我們可以在腦海中構建一下這些麵團,截圖只展示了部分:
要把這些麵團包成包子,就是要我們取出每一個麵團中,排名第3的城市。有個問題需要注意,有一些直轄市是和省並列的,而作為城市只有單獨的一行,這樣的城市我們就默認返回其本身的數據;對於非直轄市省份來說,就需要定位篩選。
拿x2來舉例,要找到這個麵團中排名第三的城市和銷售額,應該怎麼做呢?答案是直接索引,把他看作是一個DataFrame格式的表,要選取第3行的所有值,包括城市和銷售額,這裡用iloc索引,很簡單的一行代碼:
下面把我們針對直轄市的判斷和非直轄市的篩選邏輯整合成一個函數:
這個函數,將會在apply的帶領下,對每一個分組進行批量化DIY,抽取出排名第3的城市和銷售額,應用起來很簡單:
至此,每個省份,銷售額排名第三的城市已經成功篩選出來。回顧整個操作流程,先排序,後分組,最後通過定義函數傳入apply,提取出我們的目標值。分組後數據的抽象形態,以及如何判斷和取出我們需要的值,是解決問題的關鍵和難點。
「報告老闆!篩選任務已經完成!」apply在握,小Z底氣變得格外的足。
作者:周志鵬,2年數據分析,深切感受到數據分析的有趣和學習過程中缺少案例的無奈,遂新開公眾號「數據不吹牛」,定期更新數據分析相關技巧和有趣案例(含實戰數據集),歡迎大家關注交流。
聲明:本文為作者投稿,版權歸作者個人所有。