天天看點

使用pandas進行資料清洗

目錄:

資料表中的重複值

duplicated()

drop_duplicated()

資料表中的空值/缺失值

isnull()&notnull()

dropna()

fillna()

資料間的空格

檢視資料中的空格

去除資料中的空格

大小寫轉換

資料中的異常和極端值

replace()

更改資料格式

astype()

to_datetime()

資料分組

cut()

資料分列

split()

 資料清洗是一項複雜且繁瑣(kubi)的工作,同時也是整個資料分析過程中最為重要的環節。有人說一個分析項目80%的時間都是在清洗資料,這聽起來有些匪夷所思,但在實際的工作中确實如此。資料清洗的目的有兩個,第一是通過清洗讓資料可用。第二是讓資料變的更适合進行後續的分析工作。換句話說就是有”髒”資料要洗,幹淨的資料也要洗。本篇文章将介紹幾種簡單的使用python進行資料清洗的方法。

使用pandas進行資料清洗

開始之前還是先在python中導入需要使用的庫檔案,然後進行資料讀取,并建立名為loandata的資料表。這裡為了更好的展示清洗的步驟和結果,我們使用的是lendingclub公開資料中的一小部分。

1

2

3

<code>import</code> <code>numpy as np</code>

<code>import</code> <code>pandas as pd</code>

<code>loandata</code><code>=</code><code>pd.dataframe(pd.read_excel(</code><code>'loandata.xlsx'</code><code>))</code>

使用pandas進行資料清洗

資料清洗的目的有兩個,第一是通過清洗讓髒資料變的可用。這也是我們首先要解決的問題。無論是線下人工填寫的手工表,還是線上通過工具收集到的資料,又或者是crm系統中導出的資料。很多資料源都有一些這樣或者那樣的問題,例如:資料中的重複值,異常值,空值,以及多餘的空格和大小寫錯誤的問題。下面我們逐一進行處理。

第一個要處理的問題是資料表中的重複值,pandas中有兩個函數是專門用來處理重複值的,第一個是duplicated函數。duplicated函數用來查找并顯示資料表中的重複值。下面是使用這個函數對資料表進行重複值查找後的結果。

<code>loandata.duplicated()</code>

使用pandas進行資料清洗

這裡有兩點需要說明:第一,資料表中兩個條目間所有列的内容都相等時duplicated才會判斷為重複值。(duplicated也可以單獨對某一列進行重複值判斷)。第二,duplicated支援從前向後(first),和從後向前(last)兩種重複值查找模式。預設是從前向後進行重複值的查找和判斷。換句話說就是将後出現的相同條件判斷為重複值。在前面的表格中索引為4的1311748和索引為1的條目相同。預設情況下後面的條目在重複值判斷中顯示為true。

pandas中的drop_duplicates函數用來删除資料表中的重複值,判斷标準和邏輯與duplicated函數一樣。使用drop_duplicates函數後,python将傳回一個隻包含唯一值的資料表。下面是使用drop_duplicates函數後的結果。與原始資料相比減少了3行,仔細觀察可以發現,drop_duplicates預設也是使用了first模式删除了索引為4的重複值,以及後面的另外兩個重複值。

<code>loandata.drop_duplicates()</code>

使用pandas進行資料清洗

第二個要處理的問題是資料表中的空值,在python中空值被顯示為nan。在處理空值之前我們先來檢查下資料表中的空值數量。對于一個小的資料表,我們可以人工查找,但對于較為龐大的資料表,就需要尋找一個更為友善快捷的方法了。首先,對關鍵字段進行空值查找。這裡我們分别選擇了對loan_amnt字段和annual_inc字段查找空值。

pandas中查找資料表中空值的函數有兩個,一個是函數isnull,如果是空值就顯示true。另一個函數notnull正好相反,如果是空值就顯示false。以下兩個函數的使用方法以及通過isnull函數獲得的空值數量。

<code>loandata.isnull()</code>

<code>loandata.notnull()</code>

通過isnull函數和value_counts函數分别獲得了loan_amnt列和annual_inc列中的空值資料量。

使用pandas進行資料清洗
使用pandas進行資料清洗

對于空值有兩種處理的方法,第一種是使用fillna函數對空值進行填充,可以選擇填充0值或者其他任意值。第二種方法是使用dropna函數直接将包含空值的資料删除。

<code>loandata.fillna(</code><code>0</code><code>)</code>

<code>loandata.dropna()</code>

這裡我們選擇對空值資料進行填充,首先處理loan_amnt列中的空值。通過totalpymnt字段和total_tec_int字段值相減計算出loan_amnt列中的近似值。因為這裡除了利息以外還可能包括一些逾期費,手續費和罰息等,是以隻能獲得一個實際貸款金額近似值。由于貸款金額通常是一個整數,是以我們在代碼的最後對格式進行了轉換。

<code>loandata[</code><code>'loan_amnt'</code><code>]</code><code>=</code><code>loandata[</code><code>'loan_amnt'</code><code>].fillna(loandata[</code><code>'total_pymnt'</code><code>]</code><code>-</code><code>loandata[</code><code>'total_rec_int'</code><code>]).astype(np.int64)</code>

使用pandas進行資料清洗

對于annual_inc列,在原始資料表中沒有可用的輔助列進行計算,是以我們選擇用現有資料的均值進行填充。這裡可以看到貸款使用者的收入均值為50060美金。使用這個值對annual_inc中的空值進行填充。

<code>loandata[</code><code>'annual_inc'</code><code>]</code><code>=</code><code>loandata[</code><code>'annual_inc'</code><code>].fillna(loandata[</code><code>'annual_inc'</code><code>].mean())</code>

使用pandas進行資料清洗

第三個要處理的是資料中的空格。空格會影響我們後續會資料的統計和計算。從下面的結果中就可以看出空格對于正常的資料統計造成的影響。

我們再對loan_status列進行頻率統計時,由于空格的問題,相同的貸款狀态被重複計算。造成統計結果不可用。是以,我們需要解決字段中存在的空格問題。

<code>loandata[</code><code>'loan_status'</code><code>].value_counts()</code>

使用pandas進行資料清洗

python中去除空格的方法有三種,第一種是去除資料兩邊的空格,第二種是單獨去除左邊的空格,第三種是單獨去除右邊的空格。

<code>loandata[</code><code>'term'</code><code>]</code><code>=</code><code>loandata[</code><code>'term'</code><code>].</code><code>map</code><code>(</code><code>str</code><code>.strip)</code>

<code>loandata[</code><code>'term'</code><code>]</code><code>=</code><code>loandata[</code><code>'term'</code><code>].</code><code>map</code><code>(</code><code>str</code><code>.lstrip)</code>

<code>loandata[</code><code>'term'</code><code>]</code><code>=</code><code>loandata[</code><code>'term'</code><code>].</code><code>map</code><code>(</code><code>str</code><code>.rstrip)</code>

這裡我們使用去除兩邊的空格來處理loan_status列中的空格。以下是具體的代碼和去除空格後的結果。

使用pandas進行資料清洗

重新檢視loan_status列中每種貸款狀态的頻率,之前空格造成的影響已經沒有了,但這裡還有個問題,就是大小寫的問題。是以,我們還需要對每種貸款狀态的大小寫進行統一化處理。這是我們第四個要處理的問題。

使用pandas進行資料清洗

大小寫轉換的方法也有三種可以選擇,分别為全部轉換為大寫,全部轉換為小寫,和轉換為首字母大寫。

<code>loandata[</code><code>'term'</code><code>]</code><code>=</code><code>loandata[</code><code>'term'</code><code>].</code><code>map</code><code>(</code><code>str</code><code>.upper)</code>

<code>loandata[</code><code>'term'</code><code>]</code><code>=</code><code>loandata[</code><code>'term'</code><code>].</code><code>map</code><code>(</code><code>str</code><code>.lower)</code>

<code>loandata[</code><code>'term'</code><code>]</code><code>=</code><code>loandata[</code><code>'term'</code><code>].</code><code>map</code><code>(</code><code>str</code><code>.title)</code>

這裡我們将所有貸款狀态轉換為首字母大寫模式,并再次進行頻率統計。從下面的結果中可以看出,結果以及消除了空格和大小寫字母混亂的影響。清晰的顯示了貸款的三種狀态出現的頻率。

使用pandas進行資料清洗

最後我們還需要對資料表中關鍵字段的内容進行檢查,確定關鍵字段中内容的統一。主要包括資料是否全部為字元,或數字。下面我們對emp_length列進行檢驗,此列内容由數字和字元組成,如果隻包括字元,說明可能存在問題。下面的代碼中我們檢查該列是否全部為字元。答案全部為false。

<code>loandata[</code><code>'emp_length'</code><code>].</code><code>apply</code><code>(</code><code>lambda</code> <code>x: x.isalpha())</code>

使用pandas進行資料清洗

除此之外,還能檢驗該列的内容是否全部為字母或數字。或者是否全部為數字。

<code>loandata[</code><code>'emp_length'</code><code>].</code><code>apply</code><code>(</code><code>lambda</code> <code>x: x. isalnum ())</code>

<code>loandata[</code><code>'emp_length'</code><code>].</code><code>apply</code><code>(</code><code>lambda</code> <code>x: x. isdigit ())</code>

第五個要處理的問題是資料中的異常值和極端值,發現異常值和極端值的方法是對資料進行描述性統計。使用describe函數可以生成描述統計結果。其中我們主要關注最大值(max)和最小值(min)情況。

檢查異常和極端值

下面是對資料表進行描述統計的結果,其中loan_amnt的最大值和最小值分别為100000美金和36美金,這不符合業務邏輯,是以可以判斷為異常值。

<code>loandata.describe().astype(np.int64).t</code>

使用pandas進行資料清洗

異常資料替換

對于異常值資料我們這裡選擇使用replace函數對loan_amnt的異常值進行替換,這裡替換值選擇為loan_amnt的均值。下面是具體的代碼和替換結果。

<code>loandata.replace([</code><code>100000</code><code>,</code><code>36</code><code>],loandata[</code><code>'loan_amnt'</code><code>].mean())</code>

使用pandas進行資料清洗

資料清洗的第二個目的是讓資料更加适合後續的分析工作。提前對資料進行預處理,後面的挖掘和分析工作會更加高效。這些預處理包括資料格式的處理,資料分組和對有價值資訊的提取。下面我們逐一來介紹這部分的操作過程和使用到的函數。

第一步是更改和規範資料格式,所使用的函數是astype。下面是更改資料格式的代碼。對loan_amnt列中的資料,由于貸款金額通常為整數,是以我們資料格式改為int64。如果是利息字段,由于會有小數,是以通常設定為float64。

<code>loandata[</code><code>'loan_amnt'</code><code>]</code><code>=</code><code>loandata[</code><code>'loan_amnt'</code><code>].astype(np.int64)</code>

在資料格式中還要特别注意日期型的資料。日期格式的資料需要使用to_datatime函數進行處理。下面是具體的代碼和處理後的結果。

<code>loandata[</code><code>'issue_d'</code><code>]</code><code>=</code><code>pd.to_datetime(loandata[</code><code>'issue_d'</code><code>])</code>

格式更改後可以通過dtypes函數來檢視,下面顯示了每個字段的資料格式。

<code>loandata.dtypes</code>

使用pandas進行資料清洗

第二步是對資料進行分組處理,在資料表的open_acc字段記錄了貸款使用者的賬戶數量,這裡我們可以根據賬戶數量的多少對使用者進行分級,5個賬戶以下為a級,5-10個賬戶為b級,依次類推。下面是具體的代碼和處理結果。

<code>bins</code><code>=</code> <code>[</code><code>0</code><code>,</code><code>5</code><code>,</code><code>10</code><code>,</code><code>15</code><code>,</code><code>20</code><code>]</code>

<code>group_names</code><code>=</code> <code>[</code><code>'a'</code><code>,</code><code>'b'</code><code>,</code><code>'c'</code><code>,</code><code>'d'</code><code>]</code>

<code>loandata[</code><code>'categories'</code><code>]</code><code>=</code> <code>pd.cut(loandata[</code><code>'open_acc'</code><code>], bins, labels</code><code>=</code><code>group_names)</code>

首先設定了資料分組的依據,然後設定每組對應的名稱。最後使用cut函數對資料進行分組并将分組後的名稱添加到資料表中。

使用pandas進行資料清洗

第四步是資料分列,這個操作和excel中的分列功能很像,在原始資料表中grade列中包含了兩個層級的使用者等級資訊,現在我們通過資料分列将分級資訊進行拆分。資料分列操作使用的是split函數,下面是具體的代碼和分列後的結果。

<code>grade_split</code><code>=</code> <code>pd.dataframe((x.split(</code><code>'-'</code><code>)</code><code>for</code> <code>x</code><code>in</code> <code>loandata.grade),index</code><code>=</code><code>loandata.index,columns</code><code>=</code><code>[</code><code>'grade'</code><code>,</code><code>'sub_grade'</code><code>])</code>

使用pandas進行資料清洗

完成資料分列操作後,使用merge函數将資料比對會原始資料表,這個操作類似excel中的vlookup函數的功能。通過比對原始資料表中包括了分列後的等級資訊。以下是具體的代碼和比對後的結果。

<code>loandata</code><code>=</code><code>pd.merge(loandata,grade_split,right_index</code><code>=</code><code>true</code><code>, left_index</code><code>=</code><code>true</code><code>)</code>

使用pandas進行資料清洗