文章目录
一、数据处理
异常值处理
二、分训练集和测试集
三、分箱
1)我们首先把连续型变量分成一组数量较多的分类型变量,比如,将几万个样本分成100组,或50组
2)确保每一组中都要包含两种类别的样本,否则IV值会无法计算
3)我们对相邻的组进行卡方检验,卡方检验的P值很大的组进行合并,直到数据中的组数小于设定的N箱为止
4)我们让一个特征分别分成[2,3,4…20]箱,观察每个分箱个数下的IV值如何变化,找出最适合的分箱个数
5)分箱完毕后,我们计算每个箱的WOE值, bad%,观察分箱效果这些步骤都完成后,我们可以对各个特征都进行分箱,然后观察每个特征的IV值,以此来挑选特征。
确保每个箱中都有0和1
for i in range(20):
#如果第一个组没有包含正样本或负样本,向后合并
if 0 in num_bins[0][2:]:
num_bins[0:2] = [(
num_bins[0][0],
num_bins[1][1],
num_bins[0][2]+num_bins[1][2],
num_bins[0][3]+num_bins[1][3])]
continue
"""
合并了之后,第一行的组是否一定有两种样本了呢?不一定
如果原本的第一组和第二组都没有包含正样本,或者都没有包含负样本,那即便合并之后,第一行的组也还是没有
包含两种样本
所以我们在每次合并完毕之后,还需要再检查,第一组是否已经包含了两种样本
这里使用continue跳出了本次循环,开始下一次循环,所以回到了最开始的for i in range(20), 让i+1
这就跳过了下面的代码,又从头开始检查,第一组是否包含了两种样本
如果第一组中依然没有包含两种样本,则if通过,继续合并,每合并一次就会循环检查一次,最多合并20次
如果第一组中已经包含两种样本,则if不通过,就开始执行下面的代码
"""
#已经确认第一组中肯定包含两种样本了,如果其他组没有包含两种样本,就向前合并
#此时的num_bins已经被上面的代码处理过,可能被合并过,也可能没有被合并
#但无论如何,我们要在num_bins中遍历,所以写成in range(len(num_bins))
for i in range(len(num_bins)):
if 0 in num_bins[i][2:]:
num_bins[i-1:i+1] = [(
num_bins[i-1][0],
num_bins[i][1],
num_bins[i-1][2]+num_bins[i][2],
3.3.3 定义WOE和IV函数
num_bins[i-1][3]+num_bins[i][3])]
break
#如果对第一组和对后面所有组的判断中,都没有进入if去合并,则提前结束所有的循环
else:
break
"""
这个break,只有在if被满足的条件下才会被触发
也就是说,只有发生了合并,才会打断for i in range(len(num_bins))这个循环
为什么要打断这个循环?因为我们是在range(len(num_bins))中遍历
但合并发生后,len(num_bins)发生了改变,但循环却不会重新开始
举个例子,本来num_bins是5组,for i in range(len(num_bins))在第一次运行的时候就等于for i in
range(5)
range中输入的变量会被转换为数字,不会跟着num_bins的变化而变化,所以i会永远在[0,1,2,3,4]中遍历
进行合并后,num_bins变成了4组,已经不存在=4的索引了,但i却依然会取到4,循环就会报错
因此在这里,一旦if被触发,即一旦合并发生,我们就让循环被破坏,使用break跳出当前循环
循环就会回到最开始的for i in range(20)中
此时判断第一组是否有两种标签的代码不会被触发,但for i in range(len(num_bins))却会被重新运行
这样就更新了i的取值,循环就不会报错了
"""
卡方检验,合并箱体,画出IV曲线
确定了age这一列的最佳封箱个数为6,下降的转折点 。
包装封箱函数
分析:有一些数据不是连续性的值,不能被分成20箱,需要手动分箱。