原理很简单,初始分20箱或更多,先确保每箱中都含有0,1标签,对不包含0,1标签的箱向前合并,计算各箱卡方值,对卡方值最小的箱向后合并,代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
import pandas as pd
import numpy as np
import scipy
from scipy import stats
def chi_bin(DF,var,target,binnum = 5 ,maxcut = 20 ):
'''
DF:data
var:variable
target:target / label
binnum: the number of bins output
maxcut: initial bins number
'''
data = DF[[var,target]]
#equifrequent cut the var into maxcut bins
data[ "cut" ],breaks = pd.qcut(data[var],q = maxcut,duplicates = "drop" ,retbins = True )
#count 1,0 in each bin
count_1 = data.loc[data[target] = = 1 ].groupby( "cut" )[target].count()
count_0 = data.loc[data[target] = = 0 ].groupby( "cut" )[target].count()
#get bins value: min,max,count 0,count 1
bins_value = [ * zip (breaks[:maxcut - 1 ],breaks[ 1 :],count_0,count_1)]
#define woe
def woe_value(bins_value):
df_woe = pd.DataFrame(bins_value)
df_woe.columns = [ "min" , "max" , "count_0" , "count_1" ]
df_woe[ "total" ] = df_woe.count_1 + df_woe.count_0
df_woe[ "bad_rate" ] = df_woe.count_1 / df_woe.total
df_woe[ "woe" ] = np.log((df_woe.count_0 / df_woe.count_0. sum ()) / (df_woe.count_1 / df_woe.count_1. sum ()))
return df_woe
#define iv
def iv_value(df_woe):
rate = (df_woe.count_0 / df_woe.count_0. sum ()) - (df_woe.count_1 / df_woe.count_1. sum ())
iv = np. sum (rate * df_woe.woe)
return iv
#make sure every bin contain 1 and 0
##first bin merge backwards
for i in range ( len (bins_value)):
if 0 in bins_value[ 0 ][ 2 :]:
bins_value[ 0 : 2 ] = [(
bins_value[ 0 ][ 0 ],
bins_value[ 1 ][ 1 ],
bins_value[ 0 ][ 2 ] + bins_value[ 1 ][ 2 ],
bins_value[ 0 ][ 3 ] + bins_value[ 1 ][ 3 ])]
continue
##bins merge forwards
if 0 in bins_value[i][ 2 :]:
bins_value[i - 1 :i + 1 ] = [(
bins_value[i - 1 ][ 0 ],
bins_value[i][ 1 ],
bins_value[i - 1 ][ 2 ] + bins_value[i][ 2 ],
bins_value[i - 1 ][ 3 ] + bins_value[i][ 3 ])]
break
else :
break
#calculate chi-square merge the minimum chisquare
while len (bins_value)>binnum:
chi_squares = []
for i in range ( len (bins_value) - 1 ):
a = bins_value[i][ 2 :]
b = bins_value[i + 1 ][ 2 :]
chi_square = scipy.stats.chi2_contingency([a,b])[ 0 ]
chi_squares.append(chi_square)
#merge the minimum chisquare backwards
i = chi_squares.index( min (chi_squares))
bins_value[i:i + 2 ] = [(
bins_value[i][ 0 ],
bins_value[i + 1 ][ 1 ],
bins_value[i][ 2 ] + bins_value[i + 1 ][ 2 ],
bins_value[i][ 3 ] + bins_value[i + 1 ][ 3 ])]
df_woe = woe_value(bins_value)
#print bin number and iv
print ( "箱数:{},iv:{:.6f}" . format ( len (bins_value),iv_value(df_woe)))
#return bins and woe information
return woe_value(bins_value)
|
以下是效果:
初始分成10箱,目标为3箱
1
|
chi_bin(data, "age" , "SeriousDlqin2yrs" ,binnum = 3 ,maxcut = 10 )
|
箱数:8,iv:0.184862
箱数:7,iv:0.184128
箱数:6,iv:0.179518
箱数:5,iv:0.176980
箱数:4,iv:0.172406
箱数:3,iv:0.160015
min max count_0 count_1 total bad_rate woe
0 0.0 52.0 70293 7077 77370 0.091470 -0.266233
1 52.0 61.0 29318 1774 31092 0.057056 0.242909
2 61.0 72.0 26332 865 27197 0.031805 0.853755
到此这篇关于python 基于卡方值分箱算法的实现示例的文章就介绍到这了,更多相关python 卡方值分箱算法内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/wyzwyzwyzo/article/details/107354019