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

做者:xiaoyu
微信公衆號:Python數據科學
知乎:Python數據分析師python


數據科學家花了大量的時間清洗數據集,並將這些數據轉換爲他們能夠處理的格式。事實上,不少數據科學家聲稱開始獲取和清洗數據的工做量要佔整個工做的80%。正則表達式

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

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

主要內容以下:微信

  • 刪除 DataFrame 中的沒必要要 columns
  • 改變 DataFrame 的 index
  • 使用 .str() 方法來清洗 columns
  • 使用 DataFrame.applymap() 函數按元素的清洗整個數據集
  • 重命名 columns 爲一組更易識別的標籤
  • 濾除 CSV文件中沒必要要的 rows

下面是要用到的數據集:app

  • BL-Flickr-Images-Book.csv - 一份來自英國圖書館包含關於書籍信息的CSV文檔
  • university_towns.txt - 一份包含美國各大洲大學城名稱的text文檔
  • olympics.csv - 一份總結了各國家參加夏季與冬季奧林匹克運動會狀況的CSV文檔

你能夠從Real Python 的 GitHub repository 下載數據集來進行下面的例子。函數

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

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

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

>>> import pandas as pd
>>> import numpy as np

刪除DataFrame的列

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

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

Pandas提供了一個很是便捷的方法drop()函數來移除一個DataFrame中不想要的行或列。讓咱們看一個簡單的例子如何從DataFrame中移除列。

首先,咱們引入BL-Flickr-Images-Book.csv文件,並建立一個此文件的DataFrame。在下面這個例子中,咱們設置了一個pd.read_csv的相對路徑,意味着全部的數據集都在Datasets文件夾下的當前工做目錄中:

>>> df = pd.read_csv('Datasets/BL-Flickr-Images-Book.csv')
>>> df.head()

    Identifier             Edition Statement      Place of Publication  \
0         206                           NaN                    London
1         216                           NaN  London; Virtue & Yorston
2         218                           NaN                    London
3         472                           NaN                    London
4         480  A new edition, revised, etc.                    London

  Date of Publication              Publisher  \
0         1879 [1878]       S. Tinsley & Co.
1                1868           Virtue & Co.
2                1869  Bradbury, Evans & Co.
3                1851          James Darling
4                1857   Wertheim & Macintosh

                                               Title     Author  \
0                  Walter Forbes. [A novel.] By A. A      A. A.
1  All for Greed. [A novel. The dedication signed...  A., A. A.
2  Love the Avenger. By the author of 「All for Gr...  A., A. A.
3  Welsh Sketches, chiefly ecclesiastical, to the...  A., E. S.
4  [The World in which I live, and my place in it...  A., E. S.

                                   Contributors  Corporate Author  \
0                               FORBES, Walter.               NaN
1  BLAZE DE BURY, Marie Pauline Rose - Baroness               NaN
2  BLAZE DE BURY, Marie Pauline Rose - Baroness               NaN
3                   Appleyard, Ernest Silvanus.               NaN
4                           BROOME, John Henry.               NaN

   Corporate Contributors Former owner  Engraver Issuance type  \
0                     NaN          NaN       NaN   monographic
1                     NaN          NaN       NaN   monographic
2                     NaN          NaN       NaN   monographic
3                     NaN          NaN       NaN   monographic
4                     NaN          NaN       NaN   monographic

                                          Flickr URL  \
0  http://www.flickr.com/photos/britishlibrary/ta...
1  http://www.flickr.com/photos/britishlibrary/ta...
2  http://www.flickr.com/photos/britishlibrary/ta...
3  http://www.flickr.com/photos/britishlibrary/ta...
4  http://www.flickr.com/photos/britishlibrary/ta...

                            Shelfmarks
0    British Library HMNTS 12641.b.30.
1    British Library HMNTS 12626.cc.2.
2    British Library HMNTS 12625.dd.1.
3    British Library HMNTS 10369.bbb.15.
4    British Library HMNTS 9007.d.28.

咱們使用了head()方法獲得了前五個行信息,這些列提供了對圖書館有幫助的輔助信息,可是並不能很好的描述這些書籍:Edition Statement, Corporate Author, Corporate Contributors, Former owner, Engraver, Issuance type and Shelfmarks

所以,咱們能夠用下面的方法移除這些列:

>>> to_drop = ['Edition Statement',
...            'Corporate Author',
...            'Corporate Contributors',
...            'Former owner',
...            'Engraver',
...            'Contributors',
...            'Issuance type',
...            'Shelfmarks']

>>> df.drop(to_drop, inplace=True, axis=1)

在上面,咱們定義了一個包含咱們不要的列的名稱列表。接着,咱們在對象上調用drop()函數,其中inplace參數是Trueaxis參數是1。這告訴了Pandas咱們想要直接在咱們的對象上發生改變,而且它應該能夠尋找對象中被移除列的信息。

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

>>> df.head()
   Identifier      Place of Publication Date of Publication  \
0         206                    London         1879 [1878]
1         216  London; Virtue & Yorston                1868
2         218                    London                1869
3         472                    London                1851
4         480                    London                1857

               Publisher                                              Title  \
0       S. Tinsley & Co.                  Walter Forbes. [A novel.] By A. A
1           Virtue & Co.  All for Greed. [A novel. The dedication signed...
2  Bradbury, Evans & Co.  Love the Avenger. By the author of 「All for Gr...
3          James Darling  Welsh Sketches, chiefly ecclesiastical, to the...
4   Wertheim & Macintosh  [The World in which I live, and my place in it...

      Author                                         Flickr URL
0      A. A.  http://www.flickr.com/photos/britishlibrary/ta...
1  A., A. A.  http://www.flickr.com/photos/britishlibrary/ta...
2  A., A. A.  http://www.flickr.com/photos/britishlibrary/ta...
3  A., E. S.  http://www.flickr.com/photos/britishlibrary/ta...
4  A., E. S.  http://www.flickr.com/photos/britishlibrary/ta...

一樣的,咱們也能夠經過給columns參數賦值直接移除列,而就不用分別定義to_drop列表和axis了。

>>> df.drop(columns=to_drop, inplace=True)

這種語法更直觀更可讀。咱們這裏將要作什麼就很明顯了。

改變DataFrame的索引

Pandas索引index擴展了Numpy數組的功能,以容許更多多樣化的切分和標記。在不少狀況下,使用惟一的值做爲索引值識別數據字段是很是有幫助的。

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

>>> df['Identifier'].is_unique
True

讓咱們用set_index把已經存在的索引改成這個列。

>>> df = df.set_index('Identifier')
>>> df.head()
                Place of Publication Date of Publication  \
206                           London         1879 [1878]
216         London; Virtue & Yorston                1868
218                           London                1869
472                           London                1851
480                           London                1857

                        Publisher  \
206              S. Tinsley & Co.
216                  Virtue & Co.
218         Bradbury, Evans & Co.
472                 James Darling
480          Wertheim & Macintosh

                                                        Title     Author  \
206                         Walter Forbes. [A novel.] By A. A      A. A.
216         All for Greed. [A novel. The dedication signed...  A., A. A.
218         Love the Avenger. By the author of 「All for Gr...  A., A. A.
472         Welsh Sketches, chiefly ecclesiastical, to the...  A., E. S.
480         [The World in which I live, and my place in it...  A., E. S.

                                                   Flickr URL
206         http://www.flickr.com/photos/britishlibrary/ta...
216         http://www.flickr.com/photos/britishlibrary/ta...
218         http://www.flickr.com/photos/britishlibrary/ta...
472         http://www.flickr.com/photos/britishlibrary/ta...
480         http://www.flickr.com/photos/britishlibrary/ta...
技術細節:不像在SQL中的主鍵同樣,pandas的索引不保證惟一性,儘管許多索引和合並操做將會使運行時間變長若是是這樣。

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

>>> df.loc[206]
Place of Publication                                               London
Date of Publication                                           1879 [1878]
Publisher                                                S. Tinsley & Co.
Title                                   Walter Forbes. [A novel.] By A. A
Author                                                              A. A.
Flickr URL              http://www.flickr.com/photos/britishlibrary/ta...
Name: 206, dtype: object

換句話說,206是索引的第一個標籤。若是想經過位置獲取它,咱們可使用df.iloc[0],是一個基於位置的索引。

以前,咱們的索引是一個範圍索引:從0開始的整數,相似Python的內建range。經過給set_index一個列名,咱們就把索引變成了Identifier中的值。

你也許注意到了咱們經過df = df.set_index(...)的返回變量從新給對象賦了值。這是由於,默認的狀況下,這個方法返回一個被改變對象的拷貝,而且它不會直接對原對象作任何改變。咱們能夠經過設置參數inplace來避免這個問題。

df.set_index('Identifier', inplace=True)

清洗數據字段

到如今爲止,咱們移除了沒必要要的列並改變了咱們的索引變得更有意義。這個部分,咱們將清洗特殊的列,並使它們變成統一的格式,這樣能夠更好的理解數據集和增強連續性。特別的,咱們將清洗Date of PublicationPlace of Publication

根據上面觀察,全部的數據類型都是如今的objectdtype類型,差很少相似於Python中的str。

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

>>> df.get_dtype_counts()
object    6

一個須要被改變爲數值的的字段是the date of publication因此咱們作以下操做:

>>> df.loc[1905:, 'Date of Publication'].head(10)
Identifier
1905           1888
1929    1839, 38-54
2836        [1897?]
2854           1865
2956        1860-63
2957           1873
3017           1866
3131           1899
4598           1814
4884           1820
Name: Date of Publication, dtype: object

一本書只能有一個出版日期data of publication。所以,咱們須要作如下的一些事情:

  • 移除在方括號內的額外日期,任何存在的:1879[1878]。
  • 將日期範圍轉化爲它們的起始日期,任何存在的:1860-63;1839,38-54。
  • 徹底移除咱們不關心的日期,並用Numpy的NaN替換:[1879?]。
  • 將字符串nan轉化爲Numpy的NaN值。

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

regex = r'^(\d{4})'

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

\d表明任何數字,{4}重複這個規則四次。^符號匹配一個字符串最開始的部分,圓括號表示一個分組,提示pandas咱們想要提取正則表達式的部分。

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

>>> extr = df['Date of Publication'].str.extract(r'^(\d{4})', expand=False)
>>> extr.head()
Identifier
206    1879
216    1868
218    1869
472    1851
480    1857
Name: Date of Publication, dtype: object

其實這個列仍然是一個object類型,可是咱們可使用pd.to_numeric輕鬆的獲得數字的版本:

>>> df['Date of Publication'] = pd.to_numeric(extr)
>>> df['Date of Publication'].dtype
dtype('float64')

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

>>> df['Date of Publication'].isnull().sum() / len(df)
0.11717147339205986

結合str方法與Numpy清洗列

上面,你能夠觀察到df['Date of Publication'].str. 的使用。這個屬性是pandas裏的一種提高字符串操做速度的方法,並有大量的Python字符串或編譯的正則表達式上的小操做,例如.split(),.replace(),和.capitalize()

爲了清洗Place of Publication字段,咱們能夠結合pandas的str方法和numpy的np.where函數配合完成。
它的語法以下:

>>> np.where(condition, then, else)

這裏,condition可使一個類數組的對象,也能夠是一個布爾表達。若是condition值爲真,那麼then將被使用,不然使用else

它也能夠組網使用,容許咱們基於多個條件進行計算。

>>> np.where(condition1, x1, 
        np.where(condition2, x2, 
            np.where(condition3, x3, ...)))

咱們將使用這兩個方程來清洗Place of Publication因爲這列有字符串對象。如下是這個列的內容:

>>> df['Place of Publication'].head(10)
Identifier
206                                  London
216                London; Virtue & Yorston
218                                  London
472                                  London
480                                  London
481                                  London
519                                  London
667     pp. 40. G. Bryan & Co: Oxford, 1898
874                                 London]
1143                                 London
Name: Place of Publication, dtype: object

咱們看到,對於一些行,place of publication還被一些其它沒有用的信息圍繞着。若是咱們看更多的值,咱們發現這種狀況中有些行

讓咱們看看兩個特殊的:

>>> df.loc[4157862]
Place of Publication                                  Newcastle-upon-Tyne
Date of Publication                                                  1867
Publisher                                                      T. Fordyce
Title                   Local Records; or, Historical Register of rema...
Author                                                        T.  Fordyce
Flickr URL              http://www.flickr.com/photos/britishlibrary/ta...
Name: 4157862, dtype: object

>>> df.loc[4159587]
Place of Publication                                  Newcastle upon Tyne
Date of Publication                                                  1834
Publisher                                                Mackenzie & Dent
Title                   An historical, topographical and descriptive v...
Author                                               E. (Eneas) Mackenzie
Flickr URL              http://www.flickr.com/photos/britishlibrary/ta...
Name: 4159587, dtype: object

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

爲了一次性清洗這個列,咱們使用str.contains()來獲取一個布爾值。

咱們清洗的列以下:

>>> pub = df['Place of Publication']
>>> london = pub.str.contains('London')
>>> london[:5]
Identifier
206    True
216    True
218    True
472    True
480    True
Name: Place of Publication, dtype: bool

>>> oxford = pub.str.contains('Oxford')

咱們將它與np.where結合。

df['Place of Publication'] = np.where(london, 'London',
                                      np.where(oxford, 'Oxford',
                                               pub.str.replace('-', ' ')))

>>> df['Place of Publication'].head()
Identifier
206    London
216    London
218    London
472    London
480    London
Name: Place of Publication, dtype: object

這裏,np.where方程在一個嵌套的結構中被調用,condition是一個經過st.contains()獲得的布爾的Seriescontains()方法與Python內建的in關鍵字同樣,用於發現一個個體是否發生在一個迭代器中。

使用的替代物是一個表明咱們指望的出版社地址字符串。咱們也使用str.replace()將連字符替換爲空格,而後給DataFrame中的列從新賦值。

儘管數據集中還有更多的不乾淨數據,可是咱們如今僅討論這兩列。

讓咱們看看前五行,如今看起來比咱們剛開始的時候好點了。

>>> df.head()
           Place of Publication Date of Publication              Publisher  \
206                      London                1879        S. Tinsley & Co.
216                      London                1868           Virtue & Co.
218                      London                1869  Bradbury, Evans & Co.
472                      London                1851          James Darling
480                      London                1857   Wertheim & Macintosh

                                                        Title    Author  \
206                         Walter Forbes. [A novel.] By A. A        AA
216         All for Greed. [A novel. The dedication signed...   A. A A.
218         Love the Avenger. By the author of 「All for Gr...   A. A A.
472         Welsh Sketches, chiefly ecclesiastical, to the...   E. S A.
480         [The World in which I live, and my place in it...   E. S A.

                                                   Flickr URL
206         http://www.flickr.com/photos/britishlibrary/ta...
216         http://www.flickr.com/photos/britishlibrary/ta...
218         http://www.flickr.com/photos/britishlibrary/ta...
472         http://www.flickr.com/photos/britishlibrary/ta...
480         http://www.flickr.com/photos/britishlibrary/ta...
在這一點上, Place of Publication就是一個很好的須要被轉換成分類數據的類型,由於咱們能夠用整數將這至關小的惟一城市集編碼。(分類數據的使用內存與分類的數量以及數據的長度成正比)

使用applymap方法清洗整個數據集

在必定的狀況下,你將看到並非僅僅有一條列不乾淨,而是更多的。

在一些實例中,使用一個定製的函數到DataFrame的每個元素將會是頗有幫助的。pandasapplyma()方法與內建的map()函數類似,而且簡單的應用到一個DataFrame中的全部元素上。

讓咱們看一個例子。咱們將基於"university_towns.txt"文件建立一個DataFrame

$ head Datasets/univerisity_towns.txt
Alabama[edit]
Auburn (Auburn University)[1]
Florence (University of North Alabama)
Jacksonville (Jacksonville State University)[2]
Livingston (University of West Alabama)[2]
Montevallo (University of Montevallo)[2]
Troy (Troy University)[2]
Tuscaloosa (University of Alabama, Stillman College, Shelton State)[3][4]
Tuskegee (Tuskegee University)[5]
Alaska[edit]

咱們能夠看到每一個state後邊都有一些在那個state的大學城:StateA TownA1 TownA2 StateB TownB1 TownB2...。若是咱們仔細觀察state名字的寫法,咱們會發現它們都有"[edit]"的自字符串。

咱們能夠利用這個特徵建立一個含有(state,city)元組的列表,並將這個列表嵌入到DdataFrame中,

>>> university_towns = []
>>> with open('Datasets/university_towns.txt') as file:
...     for line in file:
...         if '[edit]' in line:
...             # Remember this `state` until the next is found
...             state = line
...         else:
...             # Otherwise, we have a city; keep `state` as last-seen
...             university_towns.append((state, line))

>>> university_towns[:5]
[('Alabama[edit]\n', 'Auburn (Auburn University)[1]\n'),
 ('Alabama[edit]\n', 'Florence (University of North Alabama)\n'),
 ('Alabama[edit]\n', 'Jacksonville (Jacksonville State University)[2]\n'),
 ('Alabama[edit]\n', 'Livingston (University of West Alabama)[2]\n'),
 ('Alabama[edit]\n', 'Montevallo (University of Montevallo)[2]\n')]

咱們能夠在DataFrame中包裝這個列表,並設列名爲"State"和"RegionName"。pandas將會使用列表中的每一個元素,而後設置State到左邊的列,RegionName到右邊的列。

最終的DataFrame是這樣的:

>>> towns_df = pd.DataFrame(university_towns,
...                         columns=['State', 'RegionName'])

>>> towns_df.head()
 State                                         RegionName
0  Alabama[edit]\n                    Auburn (Auburn University)[1]\n
1  Alabama[edit]\n           Florence (University of North Alabama)\n
2  Alabama[edit]\n  Jacksonville (Jacksonville State University)[2]\n
3  Alabama[edit]\n       Livingston (University of West Alabama)[2]\n
4  Alabama[edit]\n         Montevallo (University of Montevallo)[2]\n

咱們能夠像上面使用for loop來進行清洗,可是pandas提供了更簡單的辦法。咱們只須要state name和town name,而後就能夠移除因此其餘的了。這裏咱們能夠再次使用pandas的.str()方法,同時咱們也可使用applymap()將一個python callable映射到DataFrame中的每一個元素上。

咱們一直在使用"元素"這個攝於,可是咱們究竟是什麼意思呢?看看下面這個"toy"的DataFrame:

0           1
0    Mock     Dataset
1  Python     Pandas
2    Real     Python
3   NumPy     Clean

在這個例子中,每一個單元 (‘Mock’, ‘Dataset’, ‘Python’, ‘Pandas’, etc.) 都是一個元素。所以,applymap()將分別應用一個函數到這些元素上。讓咱們定義這個函數。

>>> def get_citystate(item):
...     if ' (' in item:
...         return item[:item.find(' (')]
...     elif '[' in item:
...         return item[:item.find('[')]
...     else:
...         return item

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

>>> towns_df =  towns_df.applymap(get_citystate)

首先,咱們定義一個函數,它將從DataFrame中獲取每個元素做爲本身的參數。在這個函數中,檢驗元素中是否有一個(或者[

基於上面的檢查,函數返回相應的值。最後,applymap()函數被用在咱們的對象上。如今DataFrame就看起來更幹靜了。

>>> towns_df.head()
     State    RegionName
0  Alabama        Auburn
1  Alabama      Florence
2  Alabama  Jacksonville
3  Alabama    Livingston
4  Alabama    Montevallo

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

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

重命名列和移除行

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

這種狀況下,咱們想從新命名列和移除必定的行以讓咱們只留下正確和有意義的信息。

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

$ head -n 5 Datasets/olympics.csv
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
,? Summer,01 !,02 !,03 !,Total,? Winter,01 !,02 !,03 !,Total,? Games,01 !,02 !,03 !,Combined total
Afghanistan (AFG),13,0,0,2,2,0,0,0,0,0,13,0,0,2,2
Algeria (ALG),12,5,2,8,15,3,0,0,0,0,15,5,2,8,15
Argentina (ARG),23,18,24,28,70,18,0,0,0,0,41,18,24,28,70

如今咱們將它讀入pandas的DataFrame。

>>> olympics_df = pd.read_csv('Datasets/olympics.csv')
>>> olympics_df.head()
                   0         1     2     3     4      5         6     7     8  \
0                NaN  ? Summer  01 !  02 !  03 !  Total  ? Winter  01 !  02 !
1  Afghanistan (AFG)        13     0     0     2      2         0     0     0
2      Algeria (ALG)        12     5     2     8     15         3     0     0
3    Argentina (ARG)        23    18    24    28     70        18     0     0
4      Armenia (ARM)         5     1     2     9     12         6     0     0

      9     10       11    12    13    14              15
0  03 !  Total  ? Games  01 !  02 !  03 !  Combined total
1     0      0       13     0     0     2               2
2     0      0       15     5     2     8              15
3     0      0       41    18    24    28              70
4     0      0       11     1     2     9              12

這的確有點亂!列名是以整數的字符串形式索引的,以0開始。本應該是列名的行卻處在olympics_df.iloc[0]。發生這個是由於CSV文件以0, 1, 2, …, 15起始的。

一樣,若是咱們去數據集的源文件觀察,上面的NaN真的應該是像"Country"這樣的,? Summer應該表明"Summer Games", 而01 !應該是"Gold"之類的。

所以,咱們須要作兩件事:

  • 移除第一行並設置header爲第一行
  • 從新命名列

當咱們讀CSV文件的時候,能夠經過傳遞一些參數到read_csv函數來移除行和設置列名稱。

這個函數有不少可選桉樹,可是這裏咱們只須要header
來移除第0行:

>>> olympics_df = pd.read_csv('Datasets/olympics.csv', header=1)
>>> olympics_df.head()
          Unnamed: 0  ? Summer  01 !  02 !  03 !  Total  ? Winter  \
0        Afghanistan (AFG)        13     0     0     2      2         0
1            Algeria (ALG)        12     5     2     8     15         3
2          Argentina (ARG)        23    18    24    28     70        18
3            Armenia (ARM)         5     1     2     9     12         6
4  Australasia (ANZ) [ANZ]         2     3     4     5     12         0

   01 !.1  02 !.1  03 !.1  Total.1  ? Games  01 !.2  02 !.2  03 !.2  \
0       0       0       0        0       13       0       0       2
1       0       0       0        0       15       5       2       8
2       0       0       0        0       41      18      24      28
3       0       0       0        0       11       1       2       9
4       0       0       0        0        2       3       4       5

   Combined total
0               2
1              15
2              70
3              12
4              12

咱們如今有了設置爲header的正確行,而且全部沒用的行都被移除了。記錄一下pandas是如何將包含國家的列名NaN改變爲Unnamed:0的。

爲了重命名列,咱們將使用DataFrame的rename()方法,容許你以一個映射(這裏是一個字典)從新標記一個軸。

讓咱們開始定義一個字典來將如今的列名稱(鍵)映射到更多的可用列名稱(字典的值)。

>>> new_names =  {'Unnamed: 0': 'Country',
...               '? Summer': 'Summer Olympics',
...               '01 !': 'Gold',
...               '02 !': 'Silver',
...               '03 !': 'Bronze',
...               '? Winter': 'Winter Olympics',
...               '01 !.1': 'Gold.1',
...               '02 !.1': 'Silver.1',
...               '03 !.1': 'Bronze.1',
...               '? Games': '# Games',
...               '01 !.2': 'Gold.2',
...               '02 !.2': 'Silver.2',
...               '03 !.2': 'Bronze.2'}

咱們在對象上調用rename()函數:

>>> olympics_df.rename(columns=new_names, inplace=True)

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

>>> olympics_df.head()
                   Country  Summer Olympics  Gold  Silver  Bronze  Total  \
0        Afghanistan (AFG)               13     0       0       2      2
1            Algeria (ALG)               12     5       2       8     15
2          Argentina (ARG)               23    18      24      28     70
3            Armenia (ARM)                5     1       2       9     12
4  Australasia (ANZ) [ANZ]                2     3       4       5     12

   Winter Olympics  Gold.1  Silver.1  Bronze.1  Total.1  # Games  Gold.2  \
0                0       0         0         0        0       13       0
1                3       0         0         0        0       15       5
2               18       0         0         0        0       41      18
3                6       0         0         0        0       11       1
4                0       0         0         0        0        2       3

   Silver.2  Bronze.2  Combined total
0         0         2               2
1         2         8              15
2        24        28              70
3         2         9              12
4         4         5              12

Python數據清洗:回顧

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

更多的,你學會了如何使用.str()清洗對象字段,以及如何使用applymap對整個數據集清洗。最後,咱們探索瞭如何移除CSV文件的行,而且使用rename()方法重命名列。

掌握數據清洗很是重要,由於它是數據科學的一個大的部分。你如今應該有了一個如何使用pandas和numpy進行數據清洗的基本理解了。

參考: https://realpython.com/python...

關注微信公衆號Python數據科學,獲取 120G 人工智能 學習資料。
圖片描述
圖片描述

相關文章
相關標籤/搜索