Python數據處理的26個Pandas實用技巧總結

大傢好,今天給大傢分享一篇 pandas 實用技巧,共計26個,這些技巧在你做數據處理中必不可少,歡迎收藏,喜歡記得點贊、關註。

從剪貼板中創建DataFram

假設你將一些數據儲存在Excel或者Google Sheet中,你又想要盡快地將他們讀取至DataFrame中。

你需要選擇這些數據並復制至剪貼板。然後,你可以使用read_clipboard()函數將他們讀取至DataFrame中:

圖片

和read_csv()類似,read_clipboard()會自動檢測每一列的正確的數據類型:

圖片

讓我們再復制另外一個數據至剪貼板:

圖片

神奇的是,pandas已經將第一列作為索引瞭:

圖片

需要註意的是,如果你想要你的工作在未來可復制,那麼read_clipboard()並不值得推薦。

將DataFrame劃分為兩個隨機的子集

假設你想要將一個DataFrame劃分為兩部分,隨機地將75%的行給一個DataFrame,剩下的25%的行給另一個DataFrame。

舉例來說,我們的movie ratings這個DataFrame有979行:

圖片

我們可以使用sample()函數來隨機選取75%的行,並將它們賦值給"movies_1"DataFrame:

圖片

接著我們使用drop()函數來舍棄“moive_1”中出現過的行,將剩下的行賦值給"movies_2"DataFrame:

圖片

你可以發現總的行數是正確的:

圖片

你還可以檢查每部電影的索引,或者"moives_1":

圖片

或者"moives_2":

圖片

需要註意的是,這個方法在索引值不唯一的情況下不起作用。

註: 該方法在機器學習或者深度學習中很有用,因為在模型訓練前,我們往往需要將全部數據集按某個比例劃分成訓練集和測試集。該方法既簡單又高效,值得學習和嘗試。

多種類型過濾DataFrame

讓我們先看一眼movies這個DataFrame:

In [60]:
movies.head()

Out[60]:

圖片

其中有一列是genre(類型):

圖片

比如我們想要對該DataFrame進行過濾,我們隻想顯示genre為Action或者Drama或者Western的電影,我們可以使用多個條件,以"or"符號分隔:

In [62]:
movies[(movies.genre == 'Action') |
       (movies.genre == 'Drama') |
       (movies.genre == 'Western')].head()

Out[62]:

圖片

但是,你實際上可以使用isin()函數將代碼寫得更加清晰,將genres列表傳遞給該函數:

In [64]:
movies[~movies.genre.isin(['Action', 'Drama', 'Western'])].head()

Out[64]:

圖片

如果你想要進行相反的過濾,也就是你將吧剛才的三種類型的電影排除掉,那麼你可以在過濾條件前加上破浪號:

In [64]:
movies[~movies.genre.isin(['Action', 'Drama', 'Western'])].head()

Out[64]:

圖片

這種方法能夠起作用是因為在Python中,波浪號表示“not”操作。

DataFrame篩選數量最多類別

假設你想要對movies這個DataFrame通過genre進行過濾,但是隻需要前3個數量最多的genre。

我們對genre使用value_counts()函數,並將它保存成counts(type為Series):

圖片

該Series的nlargest()函數能夠輕松地計算出Series中前3個最大值:

圖片

事實上我們在該Series中需要的是索引:

圖片

最後,我們將該索引傳遞給isin()函數,該函數會把它當成genre列表:

In [68]:
movies[movies.genre.isin(counts.nlargest(3).index)].head()

Out[68]:

圖片

這樣,在DataFrame中隻剩下Drame, Comdey, Action這三種類型的電影瞭。

處理缺失值

讓我們來看一看UFO sightings這個DataFrame:

圖片

你將會註意到有些值是缺失的

為瞭找出每一列中有多少值是缺失的,你可以使用isna()函數,然後再使用sum():

圖片

isna()會產生一個由True和False組成的DataFrame,sum()會將所有的True值轉換為1,False轉換為0並把它們加起來。

類似地,你可以通過mean()和isna()函數找出每一列中缺失值的百分比。

圖片

如果你想要舍棄那些包含瞭缺失值的列,你可以使用dropna()函數:

圖片

或者你想要舍棄那麼缺失值占比超過10%的列,你可以給dropna()設置一個閾值:

圖片

len(ufo)返回總行數,我們將它乘以0.9,以告訴pandas保留那些至少90%的值不是缺失值的列。

一個字符串劃分成多列

我們先創建另一個新的示例DataFrame:

圖片

如果我們需要將“name”這一列劃分為三個獨立的列,用來表示first, middle, last name呢?我們將會使用str.split()函數,告訴它以空格進行分隔,並將結果擴展成一個DataFrame:

圖片

這三列實際上可以通過一行代碼保存至原來的DataFrame:

圖片

如果我們想要劃分一個字符串,但是僅保留其中一個結果列呢?比如說,讓我們以", "來劃分location這一列:

圖片

如果我們隻想保留第0列作為city name,我們僅需要選擇那一列並保存至DataFrame:

圖片

Series擴展成DataFrame

讓我們創建一個新的示例DataFrame:

圖片

這裡有兩列,第二列包含瞭Python中的由整數元素組成的列表。

如果我們想要將第二列擴展成DataFrame,我們可以對那一列使用apply()函數並傳遞給Series constructor:

圖片

通過使用concat()函數,我們可以將原來的DataFrame和新的DataFrame組合起來:

圖片

對多個函數進行聚合

讓我們來看一眼從Chipotle restaurant chain得到的orders這個DataFrame:

In [82]:
orders.head(10)

Out[82]:

圖片

每個訂單(order)都有訂單號(order_id),包含一行或者多行。為瞭找出每個訂單的總價格,你可以將那個訂單號的價格(item_price)加起來。比如,這裡是訂單號為1的總價格:

圖片

如果你想要計算每個訂單的總價格,你可以對order_id使用groupby(),再對每個group的item_price進行求和。

圖片

但是,事實上你不可能在聚合時僅使用一個函數,比如sum()。**為瞭對多個函數進行聚合,你可以使用agg()函數,**傳給它一個函數列表,比如sum()和count():

圖片

這將告訴我們沒定訂單的總價格和數量。

聚合結果與DataFrame組合

讓我們再看一眼orders這個DataFrame:

In [86]:
orders.head(10)

Out[86]:

圖片

如果我們想要增加新的一列,用於展示每個訂單的總價格呢?回憶一下,我們通過使用sum()函數得到瞭總價格:

圖片

sum()是一個聚合函數,這表明它返回輸入數據的精簡版本(reduced version )。

換句話說,sum()函數的輸出:

圖片

比這個函數的輸入要小:

圖片

解決的辦法是使用transform()函數****,它會執行相同的操作但是返回與輸入數據相同的形狀

圖片

我們將這個結果存儲至DataFrame中新的一列:

In [91]:
orders['total_price'] = total_price
orders.head(10)

Out[91]:

圖片

你可以看到,每個訂單的總價格在每一行中顯示出來瞭。

這樣我們就能方便地甲酸每個訂單的價格占該訂單的總價格的百分比:

In [92]:
orders['percent_of_total'] = orders.item_price / orders.total_price
orders.head(10)

In [92]:

圖片

選取行和列的切片

讓我們看一眼另一個數據集:

In [93]:
titanic.head()

Out[93]:

圖片

這就是著名的Titanic數據集,它保存瞭Titanic上乘客的信息以及他們是否存活。

如果你想要對這個數據集做一個數值方面的總結,你可以使用describe()函數:

圖片

但是,這個DataFrame結果可能比你想要的信息顯示得更多。

如果你想對這個結果進行過濾,隻想顯示“五數概括法”(five-number summary)的信息,你可以使用loc函數並傳遞"min"到"max"的切片:

圖片

如果你不是對所有列都感興趣,你也可以傳遞列名的切片:

圖片

MultiIndexed Series重塑

Titanic數據集的Survived列由1和0組成,因此你可以對這一列計算總的存活率:

圖片

如果你想對某個類別,比如“Sex”,計算存活率,你可以使用groupby():

圖片

如果你想一次性對兩個類別變量計算存活率,你可以對這些類別變量使用groupby():

圖片

該結果展示瞭由Sex和Passenger Class聯合起來的存活率。它存儲為一個MultiIndexed Series,也就是說它對實際數據有多個索引層級。

這使得該數據難以讀取和交互,因此更為方便的是通過unstack()函數將MultiIndexed Series重塑成一個DataFrame:

圖片

該DataFrame包含瞭與MultiIndexed Series一樣的數據,不同的是,現在你可以用熟悉的DataFrame的函數對它進行操作。

創建數據透視表

如果你經常使用上述的方法創建DataFrames,你也許會發現用pivot_table()函數更為便捷

圖片

想要使用數據透視表,你需要指定索引(index), 列名(columns), (values)和聚合函數(aggregation function)。

數據透視表的另一個好處是,你可以通過****設置margins=True輕松地將行和列都加起來

圖片

這個結果既顯示瞭總的存活率,也顯示瞭Sex和Passenger Class的存活率。

最後,你可以創建交叉表(cross-tabulation),隻需要將聚合函數由"mean"改為"count":

圖片

這個結果展示瞭每一對類別變量組合後的記錄總數。

連續數據轉類別數據

讓我們來看一下Titanic數據集中的Age那一列:

圖片

它現在是連續性數據,但是如果我們想要將它轉變成類別數據呢?

一個解決辦法是對年齡范圍打標簽,比如"adult", “young adult”, “child”。實現該功能的最好方式是使用cut()函數

圖片

這會對每個值打上標簽。0到18歲的打上標簽"child",18-25歲的打上標簽"young adult",25到99歲的打上標簽“adult”。

註意到,該數據類型為類別變量,該類別變量自動排好序瞭(有序的類別變量)。

Style a DataFrame

上一個技巧在你想要修改整個jupyter notebook中的顯示會很有用。但是,一個更靈活和有用的方法是定義特定DataFrame中的格式化(style)。

讓我們回到stocks這個DataFrame:

圖片

我們可以創建一個格式化字符串的字典,用於對每一列進行格式化。然後將其傳遞給DataFrame的style.format()函數:

圖片

註意到,Date列是month-day-year的格式,Close列包含一個$符號,Volume列包含逗號。

我們可以通過鏈式調用函數來應用更多的格式化:

圖片

我們現在隱藏瞭索引,將Close列中的最小值高亮成紅色,將Close列中的最大值高亮成淺綠色。

這裡有另一個DataFrame格式化的例子:

圖片

Volume列現在有一個漸變的背景色,你可以輕松地識別出大的和小的數值。

最後一個例子:

圖片

現在,Volumn列上有一個條形圖,DataFrame上有一個標題。

請註意,還有許多其他的選項你可以用來格式化DataFrame。

額外技巧

Profile a DataFrame

假設你拿到一個新的數據集,你不想要花費太多力氣,隻是想快速地探索下。那麼你可以使用****pandas-profiling這個模塊

在你的系統上安裝好該模塊,然後使用ProfileReport()函數,傳遞的參數為任何一個DataFrame。它會返回一個互動的HTML報告:

  1. 第一部分為該數據集的總覽,以及該數據集可能出現的問題列表
  2. 第二部分為每一列的總結。你可以點擊"toggle details"獲取更多信息
  3. 第三部分顯示列之間的關聯熱力圖
  4. 第四部分為缺失值情況報告
  5. 第五部分顯示該數據及的前幾行

使用示例如下(隻顯示第一部分的報告):

圖片

以上就是Python數據處理的26個Pandas實用技巧總結的詳細內容,更多關於Python Pandas技巧的資料請關註WalkonNet其它相關文章!

推薦閱讀: