【Python 商學院】資料處理必備套件 – Pandas的常用技巧 (2)

close up of panda

前言

本篇文章會沿用上一篇的資料,告訴大家一些Pandas中常用且功能強大的函數,並詳細介紹這些函數的使用方法與語法,希望能幫助大家在進行分析時,更加方便


import pandas as pd
df=pd.read_csv('nba.csv')

iloc & loc 選取資料

df.iloc[200:300,1:6]

iloc[列:欄],這是iloc的語法邏輯,因為iloc是用index的概念,所以都是用數字來選取,如此例子就是第200到299列,第一到第五欄的資料。

df.iloc[-100:,[5,2,3,8]]

有時候我們選取的欄位會不連續,可以參考此語法,此例是倒數100列資料,第6、3、4、9欄,我們輸入的欄位順序,也會是表格資料呈現的順序

df_new=df.loc[:,['player_name', 'team_abbreviation', 'age',
       'player_height', 'player_weight', 'college', 'country', 'draft_year',
       'draft_round','gp', 'pts', 'reb', 'ast','season']]
df_new.head()

loc與iloc不同的是,如果我們的索引值或欄位名稱不是數字時,我們就是使用索引或欄位名字才能進行選取,本例子選取這14個欄位,建立一個df_new的新表格


rename 更換欄名

df_new=df_new.rename(columns={"player_name":'name',"team_abbreviation":'team'})
df_new.head()

更換欄位名稱,使用rename函數


reset_index 重設索引值

df_1920=df_new[df_new['season']=='2019-20']
df_1920=df_1920.reset_index(inplace=False)
df_1920.head()

我們選取19-20賽季,建立一個新表格,然而此時用reset_index,重新設定索引值,索引值就會從0開始

df_1920=df_1920.drop('index',axis=1)
df_1920.head()

再用drop函數,刪除”index”欄位,就建立好一個19-20賽季的表格了


sort_values 排序大小

df_1920.sort_values(by='pts',ascending=False).head()

根據”pts”欄位排序大小,如果要遞減排序,由大到小,ascending = False即可

df_1920.sort_values(by='pts',ascending=True).head()

根據”pts”欄位排序大小,如果要遞增排序,由小到大,ascending = True即可


欄位運算

df_1920['Total_pts']=df_1920['gp']*df_1920['pts']
df_1920['Total_reb']=df_1920['gp']*df_1920['reb']
df_1920['Total_ast']=df_1920['gp']*df_1920['ast']
df_1920.head()

也可以用原有欄位建立新欄位,我們這裡分別將原有的平均得分、籃板、助攻乘上出賽場數,得出總得分、總籃板、總助攻


value_counts 次數計算

df_1920['country'].value_counts().head(10)

計算country這個欄位當中,球員來自各國家的數量,來自美國的球員有394位,來自加拿大的有19位

df_1920['country'].value_counts(normalize=True).head(10)

如果想要顯示的是比率不是次數,加入normalize=True即可,約有76.6%球員來自美國,3.69%來自加拿大


groupby 聚合函數

(df_1920.groupby('team')[['Total_pts','Total_reb','Total_ast']].sum()
            .sort_values(by=(['Total_pts','Total_reb','Total_ast']),
            ascending=[0,0,1]).head())

本例根據”team”這個欄位做聚合,然後將’Total_pts’,’Total_reb’,’Total_ast’加總起來,再依’Total_pts’,’Total_reb’,’Total_ast’進行排序,先根據”Total_pts”欄位排序,ascending=0代表遞減排列,如果出現相同數值,再根據”Total_reb”此欄位進行遞減排序,以此類推,我們可以看到PHI(費城76人)總得分最高,DAL(達拉斯小牛)排名全聯盟第二。

(df_1920.groupby(['draft_round','country'])[['Total_pts','Total_reb','Total_ast']]
 ,ascending=False).head(6))

也可以一次聚合兩個欄位,本例一次聚合”draft_round”、”country”這兩個欄位,可以看到第一輪選秀且來自美國的球員總和總得分排名最高


stack、unstack 樞杻反樞杻

(df_1920.groupby(['draft_round','country'])[['Total_pts','Total_reb','Total_ast']]
 .sum().sort_values(by='Total_pts',ascending=False).head(6).unstack())

可以跟上一個結果做比較,country為一個欄位,然而當進行unstack()反樞杻後,當中的每一個國家都會自成立一個欄位,變成很多欄位的資料

(df_1920.groupby(['draft_round','country'])[['Total_pts','Total_reb','Total_ast']]
.sum().sort_values(by='Total_pts',ascending=False)
.head(6).unstack().stack())

如果進行unstack後再stack後,就可以變為最初的型態了。


pivot_table 樞紐分析表

(df_1920.pivot_table(values='pts',columns=['draft_round'],
index=['country'],margins=True,fill_value=0,sort=True
                     ,margins_name="Sum").tail())

除了groupby函數可以進行聚合計算外,當然也可以直接使用樞紐分析表pivot_table,選定數值=”pts”,欄位=”draft_round”,列=”country”即可進行運算,margins=True,代表顯示總和列跟欄,如果有空值,使用fill_value 將空值填上0,pivot_table也是資料分析的好工具,大家可以善加使用


split、replace、contains 字串處理

df_1920['season'].str.split("-",expand=True)


原先資料是”2019-20″,因此如果我們要對這個欄位進行分割,可以使用split函數,根據”-“這個符號分割,expand=True,如圖所示,分割後的資料就會生產新的兩欄了

df_1920['draft_round'].str.replace("Undrafted",'Snub')

字串中要取代文字用replace函數,將原先的”Undrafted”落選取代成”Snub”遺珠

df_1920[df_1920['name'].str.contains("Curry|James")]

用contains函數篩選出”name”這欄中名字含有”Curry”或”James”的選手


qcut、cut 分組

pd.qcut(df_1920['pts'],7)

qcut是根據相等的的百分位距進行分組,本例根據7個相等的百分位距對”pts”進行分組,如圖顯示,再-0.001~2.029為同一組,以此類推

df_1920['Score_level_qcut']=pd.qcut(df_1920['pts'],7,
            labels=["G","F","E","D","C","B","A"])
df_1920['Score_level_qcut'].value_counts()

我們根據qcut進行分組,再給予每一組一個標籤,再由value_counts()函數計算後,可以發現每一組的個數都差不多,說明qcut是根據百分位數進行分組

df_1920['Score_level_cut']=pd.cut(df_1920['pts'],bins=[0,5,10,15,20,25,30,35],labels=["G","F","E","D","C","B","A"])
df_1920['Score_level_cut'].value_counts(ascending=True)

我們也可以根據cut函數自訂分組的標準,本例子是根據 0~5、 30~35 分成7組,再給予每一組一個標籤,再由value_counts()函數計算後,可以發現每一組的個數有明顯差異,其中在30~35分的選手只有兩位

因此如果想要每組的個數都相同就使用qcut,想要每組個數有明顯差異就用cut,自訂間距


lambad、apply、def 條件建立

df_1920['reb'].apply(lambda x: 'good' if x>3.6 else 'bad')

有時候我們需要根據原有欄位下條件產生新欄位,如果當條件只有兩個時可以用lambda函數,本例子是指當”reb”的籃板數量大於3.6個時,顯示”good” ,反之,也就是小於3.6個時,顯示”bad”

def reb_ability(x):
    if x >10 :
        return "excellent"
    elif x >5:
        return  "good"
    else:
        return  "bad"

df_1920['reb'].apply(reb_ability).head(15)

然而當我們的條件三個或三個以上,建議使用def先自訂一個函數,本例的意思是當”reb”籃板數量大於10個時,顯示”excellent”,介於5~10之間,顯示”good”,如果小於5個,顯示”bad”,最後再用apply函數做連結即可


get_dummies 虛擬變數

pd.get_dummies(df_1920['draft_round'])

進行資料分析時,有時候需要將類別轉成數值,因此虛擬變數會是一個很好的解決方法,如圖”draft_round”,這一欄會有三種資料為1、2、Undrafted,分別代表第一輪、第二輪跟落選,虛擬變數的做法就是建立三個新欄位,如果原資料是1,那就會在1那一欄顯示1,其他兩欄顯示0,這種做法在羅吉斯回歸常會用到,大家可以學起來。


結論與後續

本篇文章提供很多Pandas當中常用的函數與分析技巧,希望能幫助您在處理資料時更順利,之後也會針對時間資料,介紹一些常用的函數以及更多的Pandas技巧,希望大家多多關注,感謝觀閱,您的支持是我們進步的最大動力。



作者:TKH

企業管理學碩士,對 Python、資料科學有滿滿的熱忱,就讀碩士期間開始學習程式語言、機器學習,並於碩士論文使用深度學習 LSTM 進行股價預測。

留言討論區