當前位置:
首頁 > 最新 > 使用Pandas&NumPy進行數據清洗的6大常用方法

使用Pandas&NumPy進行數據清洗的6大常用方法

數據科學家花了大量的時間清洗數據集,並將這些數據轉換為他們可以處理的格式。事實上,很多數據科學家聲稱開始獲取和清洗數據的工作量要佔整個工作的80%。

因此,如果你正巧也在這個領域中,或者計划進入這個領域,那麼處理這些雜亂不規則數據是非常重要的,這些雜亂數據包括一些缺失值,不連續格式,錯誤記錄,或者是沒有意義的異常值。

在這個教程中,我們將利用Python的和包來進行數據清洗。

主要內容如下:

刪除 中的不必要 columns

改變 的 index

使用 方法來清洗 columns

使用 函數按元素清洗整個數據集

重命名 columns 為一組更易識別的標籤

濾除 CSV文件中不必要的 rows

下面是要用到的數據集:

BL-Flickr-Images-Book.csv: 一份來自英國圖書館包含關於書籍信息的CSV文檔

university_towns.txt: 一份包含美國各大洲大學城名稱的text文檔

olympics.csv: 一份總結了各國家參加夏季與冬季奧林匹克運動會情況的CSV文檔

你可以從 的 GitHub repository 下載數據集來進行下面的例子。

注意:建議使用Jupter Notebooks來學習下面的知識。

學習之前假設你已經有了對Pandas和Numpy庫的基本認識,包括Pandas的工作基礎和對象,應用到這些對象上的常用方法,以及熟悉了NumPy的值。

讓我們導入這些模塊開始我們的學習。


經常的,你會發現數據集中不是所有的欄位類型都是有用的。例如,你可能有一個關於學生信息的數據集,包含姓名,分數,標準,父母姓名,住址等具體信息,但是你只想分析學生的分數。

這個情況下,住址或者父母姓名信息對你來說就不是很重要。這些沒有用的信息會佔用不必要的空間,並會使運行時間減慢。

Pandas提供了一個非常便捷的方法函數來移除一個DataFrame中不想要的行或列。讓我們看一個簡單的例子如何從DataFrame中移除列。

首先,我們引入文件,並創建一個此文件的DataFrame。在下面這個例子中,我們設置了一個的相對路徑,意味著所有的數據集都在文件夾下的當前工作目錄中:

我們使用了方法得到了前五個行信息,這些列提供了對圖書館有幫助的輔助信息,但是並不能很好的描述這些書籍:, , , , , 。

因此,我們可以用下面的方法移除這些列:

在上面,我們定義了一個包含我們不要的列的名稱列表。接著,我們在對象上調用函數,其中參數是,參數是。這告訴了Pandas,我們想要直接在我們的對象上發生改變,並且它應該可以尋找對象中被移除列的信息。

我們再次看一下DataFrame,我們會看到不想要的信息已經被移除了。

同樣的,我們也可以通過給參數賦值直接移除列,而就不用分別定義to_drop列表和axis了。

這種語法更直觀更可讀。我們這裡將要做什麼就很明顯了。


Pandas索引擴展了Numpy數組的功能,以允許更多多樣化的切分和標記。在很多情況下,使用唯一的值作為索引值識別數據欄位是非常有幫助的。

例如,仍然使用上一節的數據集,可以想像當一個圖書管理員尋找一個記錄,他們也許會輸入一個唯一標識來定位一本書。

讓我們用把已經存在的索引改為這個列。

技術細節:不像在SQL中的主鍵一樣,pandas的索引不保證唯一性,儘管許多索引和合併操作將會使運行時間變長如果是這樣。

我們可以用一個直接的方法來獲取每一條記錄。儘管這個詞可能看上去沒有那麼直觀,但它允許我們使用基於標籤的索引,這個索引是行的標籤或者不考慮位置的記錄。

換句話說,206是索引的第一個標籤。如果想通過位置獲取它,我們可以使用,是一個基於位置的索引。

之前,我們的索引是一個範圍索引:從0開始的整數,類似Python的內建。通過給一個列名,我們就把索引變成了中的值。

你也許注意到了我們通過的返回變數重新給對象賦了值。這是因為,默認的情況下,這個方法返回一個被改變對象的拷貝,並且它不會直接對原對象做任何改變。我們可以通過設置參數來避免這個問題。


到現在為止,我們移除了不必要的列並改變了我們的索引,讓它們變得更有意義。這個部分,我們將清洗特殊的列,並使它們變成統一的格式,這樣可以更好的理解數據集和加強連續性。特別的,我們將清洗和。

根據上面觀察,所有的數據類型都是dtype類型,差不多類似於Python中的str。

它包含了一些不能被適用於數值或是分類的數據。這也正常,因為我們正在處理這些初始值就是雜亂無章字元串的數據。

一個需要被改變為數值的的欄位是所以我們做如下操作:

一本書只能有一個出版日期。因此,我們需要做以下的一些事情:

移除在方括弧內的額外日期,任何存在的:1879[1878]。

將日期範圍轉化為它們的起始日期,任何存在的:1860-63;1839,38-54。

完全移除我們不關心的日期,並用Numpy的替換:[1879?]。

將字元串轉化為Numpy的值。

考慮這些模式,我們可以用一個簡單的正則表達式來提取出版日期:

上面正則表達式的意思在字元串開頭尋找任何四位數字,符合我們的情況。

代表任何數字,重複這個規則四次。符號匹配一個字元串最開始的部分,圓括弧表示一個分組,提示pandas我們想要提取正則表達式的部分。

讓我們看看運行這個正則在數據集上之後會發生什麼。

其實這個列仍然是一個類型,但是我們可以使用輕鬆的得到數字的版本:

這個結果中,10個值里大約有1個值缺失,這讓我們付出了很小的代價來對剩餘有效的值做計算。


上面,你可以觀察到的使用。這個屬性是pandas里的一種提升字元串操作速度的方法,並有大量的Python字元串或編譯的正則表達式上的小操作,例如,,和。

為了清洗欄位,我們可以結合pandas的方法和numpy的函數配合完成。

它的語法如下:

這裡,可以使一個類數組的對象,也可以是一個布爾表達。如果值為真,那麼將被使用,否則使用。

它也可以嵌套使用,允許我們基於多個條件進行計算。

我們將使用這兩個函數來清洗由於這列有字元串對象。以下是這個列的內容:

我們看到,對於一些行,還被一些其它沒有用的信息圍繞著。如果我們看更多的值,我們發現這種情況只適用於是"London"或者"Oxford"的行。

讓我們看看兩個特殊的:

這兩本書在同一個地方出版,但是一個有連字元,另一個沒有。

為了一次性清洗這個列,我們使用來獲取一個布爾值。

我們清洗的列如下:

我們將它與結合。

這裡,函數在一個嵌套的結構中被調用,是一個通過得到的布爾的。方法與Python內建的關鍵字一樣,用於發現一個個體是否發生在一個迭代器中。

使用的替代物是一個代表我們期望的出版社地址字元串。我們也使用將連字元替換為空格,然後給DataFrame中的列重新賦值。

儘管數據集中還有更多的不幹凈數據,但是我們現在僅討論這兩列。

讓我們看看前五行,現在看起來比我們剛開始的時候好點了。

在這一點上,就是一個很好的需要被轉換成分類數據的類型,因為我們可以用整數將這相當小的唯一城市集編碼。(分類數據的使用內存與分類的數量以及數據的長度成正比)


在一定的情況下,你將看到並不是僅僅有一條列不幹凈,而是更多的。

在一些實例中,使用一個定製的函數到DataFrame的每一個元素將會是很有幫助的。的方法與內建的函數相似,並且簡單的應用到一個中的所有元素上。

讓我們看一個例子。我們將基於"university_towns.txt"文件創建一個。

我們可以看到每個state後邊都有一些在那個state的大學城:。如果我們仔細觀察state名字的寫法,我們會發現它們都有"[edit]"的自字元串。

我們可以利用這個特徵創建一個含有元組的列表,並將這個列表嵌入到中,

我們可以在DataFrame中包裝這個列表,並設列名為"State"和"RegionName"。pandas將會使用列表中的每個元素,然後設置到左邊的列,到右邊的列。

最終的DataFrame是這樣的:

我們可以像上面使用for loop來進行清洗,但是pandas提供了更簡單的辦法。我們只需要state name和town name,然後就可以移除所以其他的了。這裡我們可以再次使用pandas的方法,同時我們也可以使用將一個python callable映射到DataFrame中的每個元素上。

我們一直在使用"元素"這個攝於,但是我們到底是什麼意思呢?看看下面這個"toy"的DataFrame:

在這個例子中,每個單元 (『Mock』, 『Dataset』, 『Python』, 『Pandas』, etc.) 都是一個元素。因此,將分別應用一個函數到這些元素上。讓我們定義這個函數。

pandas的只用一個參數,就是要應用到每個元素上的函數(callable)。

首先,我們定義一個函數,它將從DataFrame中獲取每一個元素作為自己的參數。在這個函數中,檢驗元素中是否有一個或者。

基於上面的檢查,函數返回相應的值。最後,函數被用在我們的對象上。現在DataFrame就看起來更乾淨了。

方法從DataFrame中提取每個元素,傳遞到函數中,然後覆蓋原來的值。就是這麼簡單!

技術細節:雖然是一個方便和靈活的方法,但是對於大的數據集它將會花費很長時間運行,因為它需要將python callable應用到每個元素上。一些情況中,使用Cython或者NumPY的矢量化的操作會更高效。


經常的,你處理的數據集會有讓你不太容易理解的列名,或者在頭幾行或最後幾行有一些不重要的信息,例如術語定義,或是附註。

這種情況下,我們想重新命名列和移除一定的行以讓我們只留下正確和有意義的信息。

為了證明我們如何處理它,我們先看一下"olympics.csv"數據集的頭5行:

現在我們將它讀入pandas的DataFrame。

這的確有點亂!列名是以整數的字元串形式索引的,以0開始。本應該是列名的行卻處在。發生這個是因為CSV文件以0, 1, 2, …, 15起始的。

同樣,如果我們去數據集的源文件觀察,上面的真的應該是像"Country"這樣的,應該代表"Summer Games", 而應該是"Gold"之類的。

因此,我們需要做兩件事:

移除第一行並設置header為第一行

重新命名列

當我們讀CSV文件的時候,可以通過傳遞一些參數到函數來移除行和設置列名稱。

這個函數有很多可選參數,但是這裡我們只需要來移除第0行:

我們現在有了設置為header的正確行,並且所有沒用的行都被移除了。記錄一下pandas是如何將包含國家的列名改變為的。

為了重命名列,我們將使用DataFrame的方法,允許你以一個映射(這裡是一個字典)重新標記一個軸。

讓我們開始定義一個字典將現有的列名稱(鍵)映射到更多的可用列名稱上(字典的值)。

我們在對象上調用函數:

設置為可以讓我們的改變直接反映在對象上。讓我們看看是否正確:


這個教程中,你學會了從數據集中如何使用函數去除不必要的信息,也學會了如何為數據集設置索引,以讓items可以被容易的找到。

更多的,你學會了如何使用清洗對象欄位,以及如何使用對整個數據集清洗。最後,我們探索了如何移除CSV文件的行,並且使用方法重命名列。

掌握數據清洗非常重要,因為它是數據科學的一個大的部分。你現在應該有了一個如何使用pandas和numpy進行數據清洗的基本理解了。更多內容可參考pandas和numpy官網。

參考:https://realpython.com/python-data-cleaning-numpy-pandas/


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python爬蟲之路 的精彩文章:

TAG:Python爬蟲之路 |