python分箱_python 基于卡方值分箱算法的实现示例

原理很简单,初始分20箱或更多,先确保每箱中都含有0,1标签,对不包含0,1标签的箱向前合并,计算各箱卡方值,对卡方值最小的箱向后合并,代码如下

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箱

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 卡方值分箱算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

本文标题: python 基于卡方值分箱算法的实现示例

本文地址: http://www.cppcns.com/jiaoben/python/325430.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
卡方分箱原理是一种常用的特征离散化方法,可以将连续型特征转化为离散型特征,以便于机器学习算法的处理。其基本思想是将连续型特征划分为若干个区间,使得每个区间内的样本数量尽可能相等,同时区间之间的差异尽可能大。 具体实现过程如下: 1. 将连续型特征按照大小排序,然后将其分为k个等频区间,每个区间内的样本数量相等。 2. 对于每个区间,计算其实际值与期望值之间的差异,使用卡方检验来衡量这种差异的显著性。 3. 如果某个区间的卡方值小于预设的阈值,则将其与相邻的区间合并,直到所有区间的卡方值都大于等于阈值为止。 4. 最终得到的k个区间就是特征的离散化结果。 下面是用Python实现卡方分箱示例代码: ```python import pandas as pd import numpy as np from scipy.stats import chi2_contingency def chi_merge(df, col, target, max_groups, confidence): """ 卡方分箱函数 :param df: 数据集 :param col: 需要分箱的特征列名 :param target: 目标列名 :param max_groups: 最大分组数 :param confidence: 卡方检验的置信度 :return: 分箱结果 """ # 将数据按照特征列排序 df = df.sort_values(col) # 将目标列转化为二元变量 df['target'] = np.where(df[target] == 1, 1, 0) # 计算每个分组的样本数量 total = df['target'].sum() count = df.groupby(col)['target'].agg(['sum', 'count']) count.columns = ['target', 'total'] count['non_target'] = count['total'] - count['target'] # 初始化分组 groups = [[i] for i in count.index] # 合并分组直到达到最大分组数或者所有分组的卡方值都小于阈值 while len(groups) > max_groups: # 计算相邻分组的卡方值 chi_values = [] for i in range(len(groups) - 1): group1 = groups[i] group2 = groups[i + 1] obs = np.array([[count.loc[group1, 'target'].sum(), count.loc[group1, 'non_target'].sum()], [count.loc[group2, 'target'].sum(), count.loc[group2, 'non_target'].sum()]]) chi2, p, dof, ex = chi2_contingency(obs) chi_values.append(chi2) # 找到卡方值最小的分组 min_chi = np.min(chi_values) min_index = chi_values.index(min_chi) # 合并分组 groups[min_index] = groups[min_index] + groups[min_index + 1] groups.pop(min_index + 1) # 检查合并后的分组的卡方值是否小于阈值 if min_chi < chi2.isf(1 - confidence, 1): break # 将分组转化为分箱结果 result = {} for i, group in enumerate(groups): for val in group: result[val] = i return result ``` 注意:这段代码中的卡方检验使用了scipy库中的chi2_contingency函数,需要先安装该库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值