利用python完成大數據建模前期數據準備

在建模的時間與精力分配中,數據的理解、整理與準備佔據了整個工作的80%工作量。因此,提高數據準備工作的效率可以將更重要的時間分配到模型研究上,從而提升數據建模的效率與正確率。

數據的整理與準備,一般涉及以下8點:

  1. 缺失值識別與處理
  2. 異常值識別與處理
  3. 重複值識別與處理
  4. 數值替換
  5. 行列名變更
  6. 離散數據分箱
  7. 隨機取樣
  8. 類別變數轉換啞變數(Dummy Variables)

接下來文章將逐一總結以上各點的意義及常見操作手段。

以下操作均使用pandas及numpy包

默認

import pandas as pdnimport numpy as npn

#1缺失值

數據缺失在數據建模中非常常見,幾乎每一次數據分析都會遇到。缺失值的處理一般涉及2個步驟:識別、處理。在pandas中為我們提供了isnull命令,可以非常方便的識別缺失值。

但如何處理缺失值,就需要根據實際情況討論了。

如果僅有少量數據,可以使用df.isnull()快速的查看缺失值:

#首先創建一個包含缺失值的pd.Series作為例子nstring_data =pd.Series([aardvark, artichoke, np.nan, avocado])nn#接著使用isnull()函數查看空值是否存在nstring_data.isnull()n

輸出結果如下:

輸出結果表明string_data[2]為空值

但在實際應用中,數據的量往往較大,直接查看的方式效率會很低。

此時,我們就可以依靠數據可視化來完成缺失數據的識別:

#以kaggle平台中房價預測項目數據為例,已創建了名為df_train的DataFramen#將缺失值按照柱狀圖的形式呈現,方便直觀的觀察哪些變數有缺失值及缺失的量有多少nn#統計各變數缺失數據總和nmissingTotal = df_train.isnull().sum()n#僅選取有缺失的變數nmissingExist = missingTotal[missingTotal > 0]n#將有缺失的變數按降序排列nmissingExist.sort_values(inplace=True)n#將排好的數據以柱狀圖呈現nf, ax = plt.subplots(figsize = (12, 9))nmissingExist.plot.bar()n

缺失值按升序排列

完成缺失值識別後則需要進行缺失值處理,此時需要首先完成對變數的理解,確認缺失的原因,排除標記誤解(如數據收集過程中可能用NA表示沒有,但python理解為缺失)。嘗試從源頭完成缺失值補足,如若失敗的情況下,才開始考慮統計手段。

統計學中,常用的缺失值處理手段主要包含刪除、填補

1.刪除

刪除手段主要應用於數據缺失很少或很多的極端情況。刪除命令常使用pandas中的dropna()完成。

  • 刪除缺失值所在行:數據缺失較少,且數據分布較為均勻,不適用眾數、均值補足

#刪除所有含缺失值的行ndf.dropna()#默認how = anynn#刪除所有值均為缺失值的行ndf.dropna(how = all)nn#刪除有效值小於等於x的行ndf.dropna(thresh = x)nn#刪除對應列(以A列為例)的空值對應行:ndf.drop(df.loc[df[A].isnull()].index)n

  • 刪除缺失值所在列(即刪除對應變數):變數數據缺失量較大無法補足,且無標識誤解

#刪除所有有缺失值的列ndf.dropna(axis=1, how=all)nn#刪除有效值小於等於x的列ndf.dropna(axis=1, thresh = x)n

2.填補

從數據包含的廣度、建模的可靠度角度來看,在儘可能的情況下,都應優先考慮填補。

不同的缺失情況,應考慮不同的填補方式。

首先,應優先排除標識誤解情況,即根據數據說明,數據源中變數用NA代表無或0的情況。

#將標識誤解列的NA替換為『NO』或有意義的對應值ndf[A].fillna(NO/obj, inplace = True)n

在不存在誤解的情況下,補足主要採用均值法/眾數法

#數值類變數以均值法為主ndf[A].fillna(df[A].mean(), inplace = True)n#分類變數以眾數為主ndf[B].fillna(df[B].mode()[0], inplace = True)#[0]表示選取眾數。n

其他不常用補足法:

#用前後值補足:ndf.fillna(method = ffill, inplace = True)#前值ndf.fillna(method = bfill, inplace = True)#後值n#可增加limt = x 限制補足個數n

完成missing value刪除/填補後,應檢查是否還有missing value 存在

#缺失值按列匯總,結果應為0nmissingCheck = df.isnull().sum()nmissingCheckn

#2重複值

重複值處理通常較為簡單,僅需識別後進行刪除處理即可。

一般而言,對一行中所有變數值進行重複值識別。僅所有變數都相同的,為重複。

#重複值識別,按行展示ndf.duplicated()nn#如果數據很多,則可選擇展示重複值行ndf[df.duplicated()]n

df.duplicated()的少量數據的重複值識別示例

完成重複值識別後,對重複值進行刪除處理

df.drop_duplicates()n

如果需要對某一列/幾列進行重複值刪除,可在drop_duplicates中表明,展示如下:

#某一列中的重複值ndf.drop_duplicates(A)nn#某幾列中的重複組合n#keep 默認為保留前一個有效值(index),last則為後值的indexndf.drop_duplicates([A,B], keep= last)n

#3異常值

異常值處理也相對簡單,通常識別後進行刪除處理

識別方式主要有兩種,絕對值和散點圖可視化

1.絕對值識別主要用於純數值類的異常值識別

#首先看數值的分布及範圍,主要觀察極值與均值關係ndf.describe()nn#用絕對值篩選出異常值,x為篩選範圍,根據describe結果判斷,在根據輸出進一步判斷n#也可以用排序sort_values,效果相近ndf[(np.abs(df)>x).any(1)]n

2.或者進行可視化識別,製作散點圖觀察

散點圖觀察法較為直觀,但需要逐一製圖。

#將dataFrame中想要觀察的自變數與因變數組成新的DataFrame,用於散點圖nsp = pd.concat([df[A],df[B]], axis = 1)nsp.plot.scatter(x= A, y=B)n

散點圖查看異常值示例,右下角2點面積大售價低,為明顯的異常值

#4數據轉換

數據轉換可分為替換原值以及創造新值2種情況

  • 替換原值可分為單值單替換,多值單替換,多值多替換三種情況,在單列上進行

#單值替換ndfSeries.replace(obj, obj1)nn#多值單替換ndfSeries.replace([obj, obj1], obj3)nn#多值多替換list法ndfSeries.replace([obj, obj1], [obj2, obj3])n#多值多替換dict法ndfSeries.replace({obj: obj2, obj1: obj3})n

  • 創造新值(列):基於原值創造新變數

#創建DataFrame作為基礎ndata = pd.DataFrame({food: [bacon, pulled pork, bacon, pastrami, corned beef, bacon, pastrami, honey ham, nova lox], n ounces: [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})nn#以原DataFrame中某一變數值為key,創建Dictionary,用於創建新對應值n#此示例中為food變數中食物名稱作為識別Keynmeat_to_animal = {bacon: pig, pulled pork: pig, pastrami:cow, corned beef: cow, honey ham: pig, nova lox: salmon}nn#使用map創造新變數 animal標識肉來源動物ndata[animal] = data[food].map(meat_to_animal)n

#5行列名稱更改

在某些情況下,可能會將行列的index 名稱更改為更容易理解/合適的名稱

#創建示例ndata = pd.DataFrame(np.arange(12).reshape(3,4), n index = [Ohio, Colorado, New York],n columns=[one, two, three, four])n

轉換列名:

#轉換index名稱,利用map函數ndata.index.map(lambda x: x[:4].upper())#[:4]為str的字母數量,限定名稱長度nn#第二種方式 ,使用rename函數ndata.rename(index = str.title, columns = str.upper)#index首字母大寫,列名全大寫nn#rename with dictionaryndata.rename( index = {Ohio: INDIANA},n columns = {three: peekaboo})n

#6離散分箱

用於將離散的數值變數分箱,用於進一步分析或轉換為分類變數

#可對list,np.array,pd.Series使用nages =pd.Series([20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32])nn#分箱點設置nbins = [18, 25, 35, 60, 100]nn#age Series分箱結果,顯示每個值對應的分箱結果ncats = pd.cut(ages, bins, right=False) #默認right =True,即包含右值nn#對應分箱結果,可以將數值類變數轉化為分類變數n#創建命名list,元素數量與分箱數量一一對應ngroupNames = [Youth, YoungAdult, MiddleAged, Senior]nn#基於分箱結果的新分類變數npd.cut(ages, bins, labels = groupNames)n

將ages從年齡轉化為年齡段分類

也可以對變數進行等額分箱,保證每個分箱區間大小一致

#創建np.array用於分箱ndata =np.random.randn(20)nn#如果不指定分箱點,指定分箱數量,則按照固定大小分箱,precision 為小數點後位數ncat = pd.cut(data, 4, precision = 2)n

還可以對變數進行等比例分箱

1.列明分箱數量,保證每個分箱中變數數量一致

#還可以按照分布百分比分隔,等分僅需要列明數量,使用qcut函數ncats = pd.qcut(data, 4)n

2.列明百分比區分點,進行百分比分箱

cats = pd.qcut(data, [0.1, 0.2, 0.5, 0.7, 0.9, 1])n

#7隨機取樣

隨機取樣函數可將數列進行隨機重排/部分隨機取樣

#創建DataFramendf = pd.DataFrame(np.arange(x * y).reshape(x,y))nn#隨機重新排列 permutation函數,創建reindex列,以行為準nsampler = np.random.permutation(x)nn#reindexingndf.take(sampler)n

#8分類變數轉換(Dummy variables)

對於不存在排序關係的分類變數,需要將分類變數轉化為啞變數進行分析

#將DataFrame中的某一變數進行啞變數轉換npd.get_dummies(df[key])nn#對於變數數量多,且分類變數均需要轉化為啞變數的情況,可以整體統一轉化ndf = pd.get_dummies(df)n

推薦閱讀:

TAG:数据分析 | Python |