開始以前仍是先在python中導入須要使用的庫文件,而後進行數據讀取,並建立名爲loandata的數據表。這裏爲了更好的展現清洗的步驟和結果,咱們使用的是lendingclub公開數據中的一小部分。函數
1
2
3
|
import numpy as np
import pandas as pd
loandata = pd.DataFrame(pd.read_excel( 'loandata.xlsx' ))
|
數據清洗的目的有兩個,第一是經過清洗讓髒數據變的可用。這也是咱們首先要解決的問題。不管是線下人工填寫的手工表,仍是線上經過工具收集到的數據,又或者是CRM系統中導出的數據。不少數據源都有一些這樣或者那樣的問題,例如:數據中的重複值,異常值,空值,以及多餘的空格和大小寫錯誤的問題。下面咱們逐一進行處理。工具
數據表中的重複值
第一個要處理的問題是數據表中的重複值,pandas中有兩個函數是專門用來處理重複值的,第一個是duplicated函數。Duplicated函數用來查找並顯示數據表中的重複值。下面是使用這個函數對數據表進行重複值查找後的結果。網站
1
|
loandata.duplicated()
|
這裏有兩點須要說明:第一,數據表中兩個條目間全部列的內容都相等時duplicated纔會判斷爲重複值。(Duplicated也能夠單獨對某一列進行重複值判斷)。第二,duplicated支持從前向後(first),和從後向前(last)兩種重複值查找模式。默認是從前向後進行重複值的查找和判斷。換句話說就是將後出現的相同條件判斷爲重複值。在前面的表格中索引爲4的1311748和索引爲1的條目相同。默認狀況下後面的條目在重複值判斷中顯示爲True。spa
Pandas中的drop_duplicates函數用來刪除數據表中的重複值,判斷標準和邏輯與duplicated函數同樣。使用drop_duplicates函數後,python將返回一個只包含惟一值的數據表。下面是使用drop_duplicates函數後的結果。與原始數據相比減小了3行,仔細觀察能夠發現,drop_duplicates默認也是使用了first模式刪除了索引爲4的重複值,以及後面的另外兩個重複值。3d
1
|
loandata.drop_duplicates()
|
數據表中的空值/缺失值
第二個要處理的問題是數據表中的空值,在python中空值被顯示爲NaN。在處理空值以前咱們先來檢查下數據表中的空值數量。對於一個小的數據表,咱們能夠人工查找,但對於較爲龐大的數據表,就須要尋找一個更爲方便快捷的方法了。首先,對關鍵字段進行空值查找。這裏咱們分別選擇了對loan_amnt字段和annual_inc字段查找空值。excel
Pandas中查找數據表中空值的函數有兩個,一個是函數isnull,若是是空值就顯示True。另外一個函數notnull正好相反,若是是空值就顯示False。如下兩個函數的使用方法以及經過isnull函數得到的空值數量。
1
|
loandata.isnull()
|
1
|
loandata.notnull()
|
經過isnull函數和value_counts函數分別得到了loan_amnt列和annual_inc列中的空值數據量。
對於空值有兩種處理的方法,第一種是使用fillna函數對空值進行填充,能夠選擇填充0值或者其餘任意值。第二種方法是使用dropna函數直接將包含空值的數據刪除。
1
|
loandata.fillna( 0 )
|
1
|
loandata.dropna()
|
這裏咱們選擇對空值數據進行填充,首先處理loan_amnt列中的空值。經過totalpymnt字段和total_tec_int字段值相減計算出loan_amnt列中的近似值。由於這裏除了利息之外還可能包括一些逾期費,手續費和罰息等,因此只能得到一個實際貸款金額近似值。因爲貸款金額一般是一個整數,所以咱們在代碼的最後對格式進行了轉換。
1
|
loandata[ 'loan_amnt' ] = loandata[ 'loan_amnt' ].fillna(loandata[ 'total_pymnt' ] - loandata[ 'total_rec_int' ]).astype(np.int64)
|
對於annual_inc列,在原始數據表中沒有可用的輔助列進行計算,所以咱們選擇用現有數據的均值進行填充。這裏能夠看到貸款用戶的收入均值爲50060美金。使用這個值對annual_inc中的空值進行填充。
1
|
loandata[ 'annual_inc' ] = loandata[ 'annual_inc' ].fillna(loandata[ 'annual_inc' ].mean())
|
數據間的空格
第三個要處理的是數據中的空格。空格會影響咱們後續會數據的統計和計算。從下面的結果中就能夠看出空格對於常規的數據統計形成的影響。
查看數據中的空格
咱們再對loan_status列進行頻率統計時,因爲空格的問題,相同的貸款狀態被重複計算。形成統計結果不可用。所以,咱們須要解決字段中存在的空格問題。
1
|
loandata[ 'loan_status' ].value_counts()
|
去除數據中的空格
Python中去除空格的方法有三種,第一種是去除數據兩邊的空格,第二種是單獨去除左邊的空格,第三種是單獨去除右邊的空格。
1
|
loandata[ 'term' ] = loandata[ 'term' ]. map ( str .strip)
|
1
|
loandata[ 'term' ] = loandata[ 'term' ]. map ( str .lstrip)
|
1
|
loandata[ 'term' ] = loandata[ 'term' ]. map ( str .rstrip)
|
這裏咱們使用去除兩邊的空格來處理loan_status列中的空格。如下是具體的代碼和去除空格後的結果。
從新查看loan_status列中每種貸款狀態的頻率,以前空格形成的影響已經沒有了,但這裏還有個問題,就是大小寫的問題。所以,咱們還須要對每種貸款狀態的大小寫進行統一化處理。這是咱們第四個要處理的問題。
大小寫轉換
大小寫轉換的方法也有三種能夠選擇,分別爲所有轉換爲大寫,所有轉換爲小寫,和轉換爲首字母大寫。
1
|
loandata[ 'term' ] = loandata[ 'term' ]. map ( str .upper)
|
1
|
loandata[ 'term' ] = loandata[ 'term' ]. map ( str .lower)
|
1
|
loandata[ 'term' ] = loandata[ 'term' ]. map ( str .title)
|
這裏咱們將全部貸款狀態轉換爲首字母大寫模式,並再次進行頻率統計。從下面的結果中能夠看出,結果以及消除了空格和大小寫字母混亂的影響。清晰的顯示了貸款的三種狀態出現的頻率。
最後咱們還須要對數據表中關鍵字段的內容進行檢查,確保關鍵字段中內容的統一。主要包括數據是否所有爲字符,或數字。下面咱們對emp_length列進行檢驗,此列內容由數字和字符組成,若是隻包括字符,說明可能存在問題。下面的代碼中咱們檢查該列是否所有爲字符。答案所有爲False。
1
|
loandata[ 'emp_length' ]. apply ( lambda x: x.isalpha())
|
除此以外,還能檢驗該列的內容是否所有爲字母或數字。或者是否所有爲數字。
1
|
loandata[ 'emp_length' ]. apply ( lambda x: x. isalnum ())
|
1
|
loandata[ 'emp_length' ]. apply ( lambda x: x. isdigit ())
|
數據中的異常和極端值
第五個要處理的問題是數據中的異常值和極端值,發現異常值和極端值的方法是對數據進行描述性統計。使用describe函數能夠生成描述統計結果。其中咱們主要關注最大值(max)和最小值(min)狀況。
檢查異常和極端值
下面是對數據表進行描述統計的結果,其中loan_amnt的最大值和最小值分別爲100000美金和36美金,這不符合業務邏輯,所以能夠判斷爲異常值。
1
|
loandata.describe().astype(np.int64).T
|
異常數據替換
對於異常值數據咱們這裏選擇使用replace函數對loan_amnt的異常值進行替換,這裏替換值選擇爲loan_amnt的均值。下面是具體的代碼和替換結果。
1
|
loandata.replace([ 100000 , 36 ],loandata[ 'loan_amnt' ].mean())
|
數據清洗的第二個目的是讓數據更加適合後續的分析工做。提早對數據進行預處理,後面的挖掘和分析工做會更加高效。這些預處理包括數據格式的處理,數據分組和對有價值信息的提取。下面咱們逐一來介紹這部分的操做過程和使用到的函數。
更改數據格式
第一步是更改和規範數據格式,所使用的函數是astype。下面是更改數據格式的代碼。對loan_amnt列中的數據,因爲貸款金額一般爲整數,所以咱們數據格式改成int64。若是是利息字段,因爲會有小數,所以一般設置爲float64。
1
|
loandata[ 'loan_amnt' ] = loandata[ 'loan_amnt' ].astype(np.int64)
|
在數據格式中還要特別注意日期型的數據。日期格式的數據須要使用to_datatime函數進行處理。下面是具體的代碼和處理後的結果。
1
|
loandata[ 'issue_d' ] = pd.to_datetime(loandata[ 'issue_d' ])
|
格式更改後能夠經過dtypes函數來查看,下面顯示了每一個字段的數據格式。
1
|
loandata.dtypes
|
數據分組
第二步是對數據進行分組處理,在數據表的open_acc字段記錄了貸款用戶的帳戶數量,這裏咱們能夠根據帳戶數量的多少對用戶進行分級,5個帳戶如下爲A級,5-10個帳戶爲B級,依次類推。下面是具體的代碼和處理結果。
1
2
3
|
bins = [ 0 , 5 , 10 , 15 , 20 ]
group_names = [ 'A' , 'B' , 'C' , 'D' ]
loandata[ 'categories' ] = pd.cut(loandata[ 'open_acc' ], bins, labels = group_names)
|
首先設置了數據分組的依據,而後設置每組對應的名稱。最後使用cut函數對數據進行分組並將分組後的名稱添加到數據表中。
數據分列
第四步是數據分列,這個操做和Excel中的分列功能很像,在原始數據表中grade列中包含了兩個層級的用戶等級信息,如今咱們經過數據分列將分級信息進行拆分。數據分列操做使用的是split函數,下面是具體的代碼和分列後的結果。
1
|
grade_split = pd.DataFrame((x.split( '-' ) for x in loandata.grade),index = loandata.index,columns = [ 'grade' , 'sub_grade' ])
|
完成數據分列操做後,使用merge函數將數據匹配會原始數據表,這個操做相似Excel中的Vlookup函數的功能。經過匹配原始數據表中包括了分列後的等級信息。如下是具體的代碼和匹配後的結果。
1
|
loandata = pd.merge(loandata,grade_split,right_index = True , left_index = True )
|