一、定義
數據分箱就是將連續變量離散化。
二、意義
• 離散特征可變性強,易於模型的快速迭代;
• 稀疏向量運算速度快,方便存儲;
• 變量離散化后對異常數據有很強的魯棒性;
• 特征離散以后,模型會更加穩定;
• 將邏輯回歸模型轉換成評分卡形式的時候,分箱也是必須的。
三、分類
四、卡方分箱
(1)主要思想
• 自底向上數據離散;
• 相鄰區間具有類似的類分布,則這兩個區間可以合並;
• 否則,這兩個區間應當分開。
(2)具體步驟
• 設定一個卡方閾值或分箱個數
• 對實例排序,每個實例屬於一個區間
• 計算每一對相鄰區間的卡方值
• 將卡方值最小的兩個區間合並
(3)分箱個數
限制最終的分箱個數結果,合並區間,直到分箱個數達到限制條件為止。
(4)卡方閾值
如果分箱的各區間最小卡方值小於卡方閾值,則繼續合並,直到最小卡方值超過設定閾值為止。
卡方閾值的確定:
• 根據顯著性水平和自由度得到卡方值;
• 自由度比類別數量小1。例如:有3類,自由度為2,則90%置信度(10%顯著性水平)下,卡方的值為4.6。
五、分箱評估
評估方法:
• WOE(weight of evidence),證據權重。WOE是對原始自變量的一種有監督的編碼形式。
• IV(information value),信息價值。IV是衡量特征區分度的一種指標。
(1)WOE:
要對一個變量進行WOE編碼,首先把這個變量進行分箱處理,分箱后,對於第i組,WOE的計算公式如下:
其中,pyi是第i組中響應客戶占所有樣本中所有響應客戶的比例,pni是第i組中未響應客戶占樣本中所有未響應客戶的比例。
當前這個組中響應的客戶和未響應客戶的比值,和所有樣本中這個比值的差異。這個差異是用這兩個比值的比值,再取對數來表示的。
(2)IV值
對於第i組,IV的計算公式如下:
由每個分組的IV值就可以得到整個變量的IV值,即將各個分組IV值相加:
(3)變量IV——預測能力對應表
(4)為什么使用IV值進行判斷,而不直接使用WOE值進行判斷呢?
原因:
• IV值是非負的,衡量一個變量的預測能力比較合適;
• IV值體現出當前分組中個體的數量占整體數量的比例,對變量預測能力的影響。
(5)注意事項
• 檢查最大箱,如果最大箱里面數據數量占總數據的90%以上,那么棄用這個變量;
• 當有兩個變量相關性高並且只能保留一個時,選擇IV值高的或者分箱均衡的變量;
• 如果遇到響應比例為0或者100%時:將這個分組做成一個規則,作為模型的前置條件或者補充條件;重新對變量進行分組;人工調整。
六、R實現分箱
R中的woeBinning和smbinning包可以實現⾃自動分箱。
下面介紹woeBinning包。
woeBinning函數
woe.binning對數值變量或者因子變量生成一個受監督的細分和粗分類。
woe.tree.binning對數值變量和因子變量生成監督樹狀分割。
woe.binning.plot對woe.binning或者woe.tree.binning的分箱解決方案進行數據可視化。
woe.binning.table對woe.binning或woe.tree.binning的分箱解決方案的結果進行表格化保存。
woe.binning.deploy將把woe.binning或woe.tree.binning生成並保存的分箱解決方案部署和應用到(新)數據中。
> library(woeBinning) > library(dplyr) > # 使用包自帶的數據集germancredit > data( "germancredit") > # 數據集檢視 > print(dim(germancredit))#21維,1000條數據 [1] 1000 21 > # 數據集部分變量數據獲取 > # 定性變量和定量變量 > df <- germancredit[, c( 'creditability', 'credit.amount', 'duration.in.month', 'savings.account.and.bonds', 'purpose')] > print(head(df)) creditability credit.amount duration.in.month savings.account.and.bonds purpose 1 good 1169 6 unknown/ no savings account radio/television 2 bad 5951 48 ... < 100 DM radio/television 3 good 2096 12 ... < 100 DM education 4 good 7882 42 ... < 100 DM furniture/equipment 5 bad 4870 24 ... < 100 DM car (new) 6 good 9055 36 unknown/ no savings account education > # 自動分箱操作 > binning <- woe.binning(df, 'creditability', df) > # 自動分箱后結果可視化 > woe.binning.plot(binning) > # 分箱解決方案表格化存儲 > tabulate.binning <- woe.binning.table(binning)
> tabulate.binning $`WOE Table for duration.in.month` Final.Bin Total.Count Total.Distr. bad.Count good.Count bad.Distr. good.Distr. good.Rate WOE IV 1 <= 6 82 8.2% 9 73 3.0% 10.4% 89.0% -124.6 0.093 2 <= 15 349 34.9% 80 269 26.7% 38.4% 77.1% -36.5 0.043 3 <= 30 396 39.6% 128 268 42.7% 38.3% 67.7% 10.8 0.005 4 <= Inf 173 17.3% 83 90 27.7% 12.9% 52.0% 76.6 0.113 6 Total 1000 100.0% 300 700 100.0% 100.0% 70.0% NA 0.254 $`WOE Table for savings.account.and.bonds` Final.Bin Total.Count Total.Distr. bad.Count good.Count bad.Distr. good.Distr. good.Rate 1 misc. level neg. 48 4.8% 6 42 2.0% 6.0% 87.5% 2 unknown/ no savings account + 500 <= ... < 1000 DM 246 24.6% 43 203 14.3% 29.0% 82.5% 3 ... < 100 DM + 100 <= ... < 500 DM 706 70.6% 251 455 83.7% 65.0% 64.4% 4 Total 1000 100.0% 300 700 100.0% 100.0% 70.0% WOE IV 1 -109.9 0.044 2 -70.5 0.103 3 25.2 0.047 4 NA 0.194 $`WOE Table for purpose` Final.Bin Total.Count Total.Distr. bad.Count good.Count bad.Distr. 1 misc. level neg. 9 0.9% 1 8 0.3% 2 radio/television + car (used) 383 38.3% 79 304 26.3% 3 education + car (new) + misc. level pos. + business + furniture/equipment 608 60.8% 220 388 73.3% 4 Total 1000 100.0% 300 700 100.0% good.Distr. good.Rate WOE IV 1 1.1% 88.9% -123.2 0.010 2 43.4% 79.4% -50.0 0.086 3 55.4% 63.8% 28.0 0.050 4 100.0% 70.0% NA 0.146 $`WOE Table for credit.amount` Final.Bin Total.Count Total.Distr. bad.Count good.Count bad.Distr. good.Distr. good.Rate WOE IV 1 <= 5969.95 850 85.0% 231 619 77.0% 88.4% 72.8% -13.8 0.016 2 <= 9162.7 100 10.0% 40 60 13.3% 8.6% 60.0% 44.2 0.021 3 <= Inf 50 5.0% 29 21 9.7% 3.0% 42.0% 117.0 0.078 5 Total 1000 100.0% 300 700 100.0% 100.0% 70.0% NA 0.115 > # 分箱解決方案部署和應用到新的數據集(IV值大於0.1的) > df.with.binned.vars.added <- woe.binning.deploy(df,binning, add.woe.or.dum.var = 'woe',min.iv.total = 0.1) > View(df.with.binned.vars.added) > woe.df <- df.with.binned.vars.added %>% dplyr::select(contains( "woe.")) > View(head(woe.df)) > #%>%管道函數,把左件的值發送給右件的表達式,並作為右件表達式函數的第一個參數
##雙冒號是直接引用dplyr這個包,不用library
結果: