缺失值處理是一個數(shù)據(jù)分析工作者永遠避不開的話題,如何認識與理解缺失值,運用合適的方式處理缺失值,對模型的結(jié)果有很大的影響。本期Python數(shù)據(jù)分析實戰(zhàn)學習中,我們將詳細討論數(shù)據(jù)缺失值分析與處理等相關的一系列問題。
作為數(shù)據(jù)清洗的一個重要環(huán)節(jié),一般從缺失值分析和缺失值處理兩個角度展開:-
缺失值分析
- 缺失值處理
Part 1
缺失值分析數(shù)據(jù)的缺失主要包括記錄的缺失和記錄中某個字段信息的缺失,兩者都會造成分析結(jié)果的不準確,以下從缺失值類型、產(chǎn)生的原因及影響等方面展開分析。- 缺失值類型
2、完全隨機丟失(MCAR,Missing Completely at Random)
數(shù)據(jù)的缺失是完全隨機的,不依賴于任何不完全變量或完全變量,不影響樣本的無偏性。3、非隨機丟失(MNAR,Missing not at Random)
數(shù)據(jù)的缺失與不完全變量自身的取值有關。正確的理解和判斷缺失值的類型,對工作中對缺失值分析和處理帶來很大對便利,但因沒有一套成熟但缺失值類型判斷方法,大多考經(jīng)驗處理,這里不作過多闡述。- 缺失值成因
1、信息暫時無法獲取、獲取信息代價太大;
2、信息因人為因素沒有被記錄、遺漏或丟失;3、部分對象或某些屬性不可用或不存在;4、信息采集設備故障、存儲介質(zhì)、傳輸媒體或其他物理原因造成的數(shù)據(jù)丟失。- 缺失值影響
1、使系統(tǒng)丟失大量的有用信息;
2、使系統(tǒng)中所表現(xiàn)出的不確定性更加顯著,系統(tǒng)中蘊涵的確定性成分更難把握;3、包含空值的數(shù)據(jù)會使數(shù)據(jù)挖掘過程陷入混亂,導致不可靠的輸出。- 缺失值分析
data.info(); data.describe()
來查看數(shù)據(jù)的基本情況。代碼:
>>>data.info()
輸出結(jié)果:
結(jié)果圖中綠色框是數(shù)據(jù)總索引數(shù),藍色框為每個變量的總記錄數(shù),它們的差值為每個變量的缺失值總數(shù)。代碼:
>>>data.describe()
輸出結(jié)果:
結(jié)果圖中count為每個變量的非空計數(shù),其與總索引數(shù)的差值,即為缺失值總數(shù)。
以上方法在查看數(shù)據(jù)的總體概況下表現(xiàn)較佳,但用于數(shù)據(jù)缺失值分析顯得力不從心。下面介紹幾個更加便于缺失值分析的方法。
-
統(tǒng)計缺失值
>>>importpandasaspd
>>>missing=data.isnull().sum().reset_index().rename(columns={0:'missNum'})
>>>missing.head(10)
輸出結(jié)果:
為方便展示,本例中只顯示前10個特征。從上面數(shù)據(jù)描述查看信息data.info()可以看出,本數(shù)據(jù)總計為689945條,從missNum中可以清洗看出每條特征變量的缺失情況:索引0-4為無缺失特征,索引8為缺失最少,而索引6則缺失超60萬條。
-
計算缺失值比例
>>>missing['missRate']=missing['missNum']/data.shape[0]
>>>missing.head(10)
輸出結(jié)果:data.shape[0] 得到數(shù)據(jù)記錄總數(shù)。
missing.head(10) 只顯示前10條記錄。
missNum
比數(shù)據(jù)總量data.shape[0]
得到缺失比值missRate
,這樣更加直觀地看出缺失值相對數(shù)量,便于后續(xù)選擇合適的缺失值處理。-
按照缺失率排序顯示
代碼:
>>>miss_analy=missing[missing.missRate>0].sort_values(by='missRate',ascending=False)
>>>miss_analy.head(10)
輸出結(jié)果:miss_analy 存儲的是每個變量缺失情況的數(shù)據(jù)框。
-
缺失值可視化
matplotlib庫--條形圖
利用常規(guī)matplotlib.pyplot
庫可視化出每個變量的缺失值比例,以及總體排名情況,一目了然。代碼:
>>>importmatplotlib.pyplotasplt
>>>importpylabaspl
>>>colors=['DeepSkyBlue','DeepPink','Yellow','LawnGreen','Aqua','DarkSlateGray']
>>>fig=plt.figure(figsize=(20,6))
>>>plt.bar(np.arange(miss_analy.shape[0]),list(miss_analy.missRate.values),align='center',color=colors)
>>>font={'family':'TimesNewRoman','weight':'normal','size':23,}
>>>plt.title('Histogramofmissingvalueofvariables',fontsize=20)
>>>plt.xlabel('variablesnames',font)
>>>plt.ylabel('missingrate',font)
#添加x軸標簽,并旋轉(zhuǎn)90度
>>>plt.xticks(np.arange(miss_analy.shape[0]),list(miss_analy['index']))
>>>pl.xticks(rotation=90)
#添加數(shù)值顯示
>>>forx,yinenumerate(list(miss_analy.missRate.values)):
plt.text(x,y+0.08,'{:.2%}'.format(y),ha='center',rotation=90)
>>>plt.ylim([0,1.2])
#保存圖片
>>>fig.savefig('missing.png')
>>>plt.show()
條形圖繪制參數(shù)詳解:bar(left, height, width=0.8, bottom=None, color=None, edgecolor=None, linewidth=None, tick_label=None, xerr=None, yerr=None, label = None, ecolor=None, align, log=False, **kwargs)
x:sequence of scalars 傳遞數(shù)值序列,指定條形圖中x軸上的刻度值。
height:scalar or sequence of scalars傳遞標量或標量序列,指定條形圖y軸上的高度。
width:scalar or array-like, optional,default: 0.8 指定條形圖的寬度,默認為0.8.
bottom:scalar or array-like, optional, default: 0條形基的y坐標, 用于繪制堆疊條形圖。
align:{'center', 'edge'}, optional, default: 'center'
*"center": 在 x 位置上居中。*"edge": 用 x 位置對齊條的左邊。要對齊右邊緣上的條,請通過一個負的 width 和 "align='edge' "。color:scalar or array-like, optional 指定條形圖的填充色。
edgecolor:scalar or array-like, optional 指定條形圖的邊框色。
linewidth:scalar or array-like, optional 指定條形圖邊框的寬度,如果指定為0,表示不繪制邊框。
tick_label:string or array-like,optional 指定條形圖的刻度標簽。
xerr,yerr:scalar or array-like of shape(N,) or shape(2,N), optional,defaultNone
如果 not None,表示在條形圖的基礎上添加誤差棒;值是相對于數(shù)據(jù) +/- 誤差棒大?。?/span>*標量: 對稱的+/- 誤差棒值為所有條;*shape(N,): 每個bar對稱+/- 誤差棒值;*shape(2,n): 為每個bar分別設置-和+ 誤差棒值。第一行包含較低的錯誤,第二行包含上的錯誤。* None:沒有錯誤。(默認)label:string or array-like, optional 指定條形圖的標簽,一般用以添加圖例。
ecolor:scalar or array-like, optional, default: 'black'ecolor 指定條形圖誤差棒的顏色。*align:指定x軸刻度標簽的對齊方式,默認為'center',表示刻度標簽居中對齊,如果設置為'edge',則表示在每個條形的左下角呈現(xiàn)刻度標簽。
log:bool, optional, default: False 是否對坐標軸進行l(wèi)og變換。
**kwargs 關鍵字參數(shù),用于對條形圖進行其他設置,如透明度等。
missingno庫--矩陣圖、條形圖、熱圖、樹狀圖
庫提供了一個靈活且易于使用的缺失數(shù)據(jù)可視化和實用程序的小工具集,可以快速直觀地總結(jié)數(shù)據(jù)集的完整性。mssingno
- 矩陣圖
代碼:
>>>importmissingnoasmsno
>>>msno.matrix(data,labels=True)
矩陣圖繪制參數(shù)詳解:msno.matrix(df,filter=None, n=0, p=0, sort=None, figsize=(25, 10), width_ratios=(15, 1), color=(0.25, 0.25, 0.25), fontsize=16, labels=None, sparkline=True, inline=False, freq=None, ax=None)
df:DataFrame, default None 被映射的
"DataFrame"
。filter: str, default None 用于熱圖的濾鏡??梢允?code style="text-align:left;border-width:1px;border-style:solid;border-color:rgb(231,234,237);background-color:rgb(243,244,244);padding-right:2px;padding-left:2px;font-size:.9em;">"top",
"bottom"
,或"None"
(默認)之一。n:int, default 0過濾后的數(shù)據(jù)格式中包含的最大列數(shù)。
P:int, default 0過濾后的數(shù)據(jù)框中列的最大填充百分比。
sort:str, default None 要應用的行排序順序??梢允?span>
"ascending"
、"descending"
,或"None"
(默認)。figsize:tuple, default (25, 10) 顯示的圖形的大小。
fontsize:int, default 16圖形的字體大小。
labels:list, default None是否顯示列名。如果有的話,當數(shù)據(jù)列數(shù)為50列或更少默認為基礎數(shù)據(jù)標簽,超過50列時不使用標簽。
sparkline:bool default True 是否顯示
sparkline
。width_ratios:tuple default (15,1)矩陣的寬度與
sparkline
的寬度之比。如果"sparkline=False"
,則不執(zhí)行任何操作。color:default (0.25,0.25,0.25) 填充欄的顏色。
實際使用中,直接使用默認值即能滿足大部分情況下的需求。如常用的參數(shù)labels
能夠根據(jù)數(shù)據(jù)標簽的數(shù)量自動選擇參數(shù)值。
-
條形圖
---- 是針對標簽列缺失值的簡單可視化
代碼:
>>>msno.bar(data.iloc[:,0:18])#使用默認參數(shù)即可
矩陣圖繪制參數(shù)簡介:
msno.bar(df, figsize=(24, 10), fontsize=16, labels=None, log=False, color='dimgray', inline=False, filter=None, n=0, p=0, sort=None, ax=None,)
從參數(shù)列表中可以看出,條形圖與矩陣圖參數(shù)類似,其中參數(shù)
inline
將在后面的版本中刪除,可以忽略。"The 'inline' argument has been deprecated, and will be removed in a future version"
missingno
的條形圖與matplotlib
條形圖有異曲同工之秒:封裝的庫,使用更加方便,既能看出缺失值數(shù)量,又能看出缺失值對百分比。可通過參數(shù)對特征變量按照缺失值缺失情況排序顯示。代碼:
>>>msno.bar(data.iloc[:,0:18],sort='descending')
細心的讀者不難看出,此圖與上圖(未排序)的主題風格并不相同,可利用matplotlib.pyplot
來設置主題:
>>>importmatplotlib.pyplotasplt
>>>plt.style.use('seaborn')
>>>%matplotlibinline
- 熱圖
----相關性熱圖措施無效的相關性:一個變量的存在或不存在如何強烈影響的另一個的存在。
代碼:
>>>msno.heatmap(data.iloc[:,0:13])#使用默認參數(shù)即可
輸出結(jié)果:
兩個變量的無效相關范圍從-1(如果一個變量出現(xiàn),另一個肯定沒有)到0(出現(xiàn)或不出現(xiàn)的變量對彼此沒有影響)到1(如果一個變量出現(xiàn),另一個肯定也是)。
數(shù)據(jù)全缺失或全空對相關性是沒有意義的,所以就在圖中就沒有了,比如date列就沒有出現(xiàn)在圖中。
大于-1和小于1表示有強烈的正相關和負相關,但是由于極少數(shù)的臟數(shù)據(jù)所以并不絕對,這些例外的少數(shù)情況需要在數(shù)據(jù)加工時候予以注意。
熱圖方便觀察兩個變量間的相關性,但是當數(shù)據(jù)集變大,這種結(jié)論的解釋性會變差。
-
樹狀圖
代碼:
>>>msno.dendrogram(data.iloc[:,0:18])
輸出結(jié)果:樹狀圖采用由scipy提供的層次聚類算法通過它們之間的無效相關性(根據(jù)二進制距離測量)將變量彼此相加。在樹的每個步驟中,基于哪個組合最小化剩余簇的距離來分割變量。變量集越單調(diào),它們的總距離越接近0,并且它們的平均距離越接近零。
在0距離處的變量間能彼此預測對方,當一個變量填充時另一個總是空的或者總是填充的,或者都是空的。
樹葉的高度顯示預測錯誤的頻率。
和矩陣Matrix一樣,只能處理50個變量,但是通過簡單的轉(zhuǎn)置操作即可處理更多更大的數(shù)據(jù)集。
這樣的統(tǒng)計計算以及可視化基本已經(jīng)看出哪些變量缺失,以及缺失比例情況,對數(shù)據(jù)即有個缺失概況。
Part 2缺失值處理
缺失值處理思路
先通過一定的方法找到缺失值,接著分析缺失值在整體樣本中的分布占比,以及缺失值是否具有顯著的無規(guī)律分布特征,即第一部分介紹到缺失值分析。然后考慮使用的模型中是否滿足缺失值的自動處理,最后決定采用那種缺失值處理方法,即接下來介紹到缺失值處理。缺失值處理?法的選擇,主要依據(jù)是業(yè)務邏輯和缺失值占比,在對預測結(jié)果的影響盡可能小的情況下,對缺失值進行處理以滿足算法需求,所以要理解每個缺失值處理方法帶來的影響,下?的缺失值處理?法沒有特殊說明均是對特征(列,變量)的處理。
- 丟棄
-
占?較多,如80%以上時,刪除缺失值所在的列如果某些行缺失值占比較多,或者缺失值所在字段是苛刻的必須有值的,刪除行。
#刪除‘col’列
>>>data.drop('col',axis=1,inplace=True)
#刪除數(shù)據(jù)表中含有空值的行
>>>data.dropna()
#丟棄某幾列有缺失值的行
>>>data.dropna(axis=0,subset=['a','b'],inplace=True)
#去掉缺失比例大于80%以上的變量
>>>data.dropna(thresh=len(data)*0.2,axis=1)
參數(shù)詳解:
data.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
inplace : bool, default False 如果為真,執(zhí)行就地操作并返回None。
subset : array-like, optional 要考慮沿著其他軸的標簽,例如,如果您要刪除行,這些將是要包含的列的列表。
thresh : int, optional, default 'any' 只保留至少有thresh個非na值的行。
how : {'any', 'all'},default 'any' 確定是否從DataFrame中刪除了行或列至少有一個NA或全部NA。* 'any':如果有任何NA值,刪除行或列。* 'all':如果所有的值都是NA,刪除行或列。
axis : {0 or 'index', 1 or 'columns'}, default 0 確定包含缺失值的行或列是否為移除。* 0,或“索引”:刪除包含缺失值的行。* 1,或“columns”:刪除包含缺失值的列。
- 補全
-
占比一般,30%-80%時,將缺失值作為單獨的?個分類如果特征是連續(xù)的,則其他已有值分箱如果特征是分類的,考慮其他分類是否需要重分箱
-
- 等深分箱法(統(tǒng)一權(quán)重法): 將數(shù)據(jù)集按記錄(行數(shù))分箱,每箱具有相同的記錄數(shù)(元素個數(shù))。每箱記錄數(shù)稱為箱子深度(權(quán)重)。
- 等寬分箱法(統(tǒng)一區(qū)間法): 使數(shù)據(jù)集在整個屬性值的區(qū)間上平均分布,即每個箱的區(qū)間范圍(箱子寬度)是一個常量。
- 用戶自定義區(qū)間:當用戶明確希望觀察某些區(qū)間范圍內(nèi)的數(shù)據(jù)時,可根據(jù)需要自定義區(qū)間。
-
占?比少,10%-30%時,一般使用模型法,基于已有的其他字段,將缺失字段作為目標變量進行預測,從而得到最為可能的不全值。連續(xù)型變量用回歸模型補全;分類變量用分類模型補全。如進行多重插補、KNN算法填充、隨機森林填補法,我們認為若干特征之間有相關性的,可以相互預測缺失值。
# interpolate()插值法,缺失值前后數(shù)值的均值,但是若缺失值前后也存在缺失,則不進行計算插補。
>>>data['a']=data['a'].interpolate()
#用前面的值替換,當?shù)谝恍杏腥笔е禃r,該行利用向前替換無值可取,仍缺失
>>>data.fillna(method='pad')
#用后面的值替換,當最后一行有缺失值時,該行利用向后替換無值可取,仍缺失
>>>data.fillna(method='backfill')#用后面的值替換
B. 多重插補法
常見插值函數(shù):牛頓插值法、分段插值法、樣條插值法、Hermite插值法、埃爾米特插值法和拉格朗日插值法,以下詳細介紹拉格朗日插值法的原理和使用。
>>>fromscipy.interpolateimportlagrange
>>>x=[1,2,3,4,7]
>>>y=[5,7,10,3,9]
>>>f=lagrange(x,y)
'numpy.lib.polynomial.poly1d'>4
#這一行是輸出a的類型,以及最高次冪。
>>>print(f)
432
0.5472x-7.306x+30.65x-47.03x+28.13
#第一行和第二行就是插值的結(jié)果,顯示出的函數(shù)。第二行的數(shù)字是對應下午的x的冪,
>>>print(f(1),f(2),f(3))
5.0000000000000077.00000000000001410.00000000000005
#此行是代入的x值,得到的結(jié)果。即用小括號f(x)的這種形式,可以直接得到計算結(jié)果。
>>>print(f[0],f[2],f[3])
28.1333333333333430.65277777777778-7.3055555555555545
#此行是提取出的系數(shù)。即可以用f[a]這種形式,來提取出來對應冪的系數(shù)。
C. KNN填充利用KNN算法填充,將目標列當做目標標簽,利用非缺失的數(shù)據(jù)進行KNN算法擬合,最后對目標標簽缺失值進行預測。(對于連續(xù)特征一般是用加權(quán)平均法,對于離散特征一般是用加權(quán)投票法)拉格朗日插值法
from scipy.interpolate import lanrange
對于空間上已知的n個點(無兩點在一條直線上)可以找到一個 n-1 次多項式 ,使得多項式曲線過這個點。需滿?的假設:MAR:Missing At Random,數(shù)據(jù)缺失的概率僅和已觀測的數(shù)據(jù)相關,即缺失的概率與未知的數(shù)據(jù)無關,即與變量的具體數(shù)值無關。迭代(循環(huán))次數(shù)可能的話超過40,選擇所有的變量甚至額外的輔助變量。
>>>fromsklearn.neighborsimportKNeighborsClassifier,KNeighborsRegressor
>>>defKNN_filled_func(X_train,y_train,X_test,k=3,dispersed=True):
..."""
...X_train為目標列中不含缺失值的數(shù)據(jù)(不包括目標列)
...y_train為不含缺失值的目標標簽
...X_test為目標列中為缺失值的數(shù)據(jù)(不包括目標列)
..."""
...ifdispersed:
...KNN=KNeighborsClassifier(n_neighbors=k,weights="distance")
...else:
...KNN=KNeighborsRegressor(n_neighbors=k,weights="distance")
...KNN.fit(X_train,y_train)
...returnX_test.index,KNN.predict(X_test)
D. 隨機森林填補法
其思想與KNN填補法類似。
>>>fromsklearn.ensembleimportRandomForestRegressor,RandomForestClassifier
>>>defRF_filled_func(X_train,y_train,X_test,k=3,dispersed=True):
..."""
...X_train為目標列中不含缺失值的數(shù)據(jù)(不包括目標列)
...y_train為不含缺失值的目標標簽
...X_test為目標列中為缺失值的數(shù)據(jù)(不包括目標列)
..."""
...ifdispersed:
...rf=RandomForestRegressor()
...else:
...rf=RandomForestClassifier()
...rf.fit(X_train,y_train)
...returnX_test.index,rf.predict(X_test)
- 占?較少,10%以下,一般使用統(tǒng)計法(連續(xù)型變量用均值、中位數(shù)、加權(quán)均值;分類型變量用眾數(shù))。
-
平均值適用于近似正態(tài)分布數(shù)據(jù),觀測值較為均勻散布均值周圍;
-
中位數(shù)適用于偏態(tài)分布或者有離群點數(shù)據(jù),中位數(shù)是更好地代表數(shù)據(jù)中心趨勢;
-
眾數(shù)一般用于類別變量,無大小、先后順序之分。
pandas 內(nèi) df.fillna()
處理缺失值
#均值填充
>>>data['col']=data['col'].fillna(data['col'].means())
#中位數(shù)填充
>>>data['col']=data['col'].fillna(data['col'].median())
#眾數(shù)填充
>>>data['col']=data['col'].fillna(stats.mode(data['col'])[0][0])
-
sklearn.preprocessing.Imputer()
處理缺失值
>>>fromsklearn.preprocessingimportImputer
>>>imr=Imputer(missing_values='NaN',strategy='mean',axis=0)
>>>imputed_data=pd.DataFrame(imr.fit_transform(df.values),columns=df.columns)
>>>imputed_data
此外還有結(jié)合實際,運用專家補全。
-
真值轉(zhuǎn)化法
認為缺失值本身以一種數(shù)據(jù)分布規(guī)律存在。將變量的實際值和缺失值都作為輸入維度參與后續(xù)數(shù)據(jù)處理和模型計算中。 -
不處理
對于一些模型對缺失值有容忍度或靈活處理方法,可不處理缺失值。如KNN、決策樹、隨機森林、神經(jīng)網(wǎng)絡、樸素貝葉斯、DBSCAN等。
-
神經(jīng)網(wǎng)絡
+關注
關注
42文章
4734瀏覽量
100420 -
數(shù)據(jù)
+關注
關注
8文章
6820瀏覽量
88747 -
eda
+關注
關注
71文章
2685瀏覽量
172735 -
信息采集
+關注
關注
0文章
81瀏覽量
21175 -
樸素貝葉斯
+關注
關注
0文章
12瀏覽量
3369
原文標題:缺失值處理,你真的會了嗎?
文章出處:【微信號:DBDevs,微信公眾號:數(shù)據(jù)分析與開發(fā)】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論