1.数据分箱
# 首先通过如下代码构造数据:
import pandas as pd
data = pd.DataFrame([[22,1],[25,1],[20,0],[35,0],[32,1],[38,0],[50,0],[46,1]], columns=['年龄', '是否违约'])
data
# 有了数据之后,根据“年龄”这一特征变量进行数据分箱,代码如下:
data_cut = pd.cut(data['年龄'], 3)
data_cut
2.统计各个分箱样本总数、坏样本数和好样本数
# 统计总客户数
cut_group_all = data['是否违约'].groupby(data_cut).count()
# 统计违约客户
cut_y = data['是否违约'].groupby(data_cut).sum()
# 统计未违约客户
cut_n = cut_group_all - cut_y
# 这里展示下cut_group_all的结果,如下所示:
cut_group_all
# 通过2.2.1节相关知识点将cut_group_all、cut_y、cut_n进行汇总,代码如下,这里我们将违约客户命名为“坏样本”,非违约客户命名为“好样本”。
df = pd.DataFrame() # 创建一个空DataFrame用来汇总数据
df['总数'] = cut_group_all
df['坏样本'] = cut_y
df['好样本'] = cut_n
df
3.统计各分箱中坏样本比率和好样本比率
# 计算坏样本%和好样本%
df['坏样本%'] = df['坏样本'] / df['坏样本'].sum()
df['好样本%'] = df['好样本'] / df['好样本'].sum()
df
4.计算WOE值
import numpy as np
df['WOE'] = np.log(df['坏样本%'] / df['好样本%'])
df
在实际应用中,我们不希望WOE值出现无穷大(这样会导致之后计算的IV值也变为无穷大,丧失了IV值的意义),但是有的时候可能由于数据特殊性及分箱的原因,它还是出现了WOE值为无穷大的情况(某个分箱中只含有一种类别的数据),此时解决办法是当WOE值为无穷大时,将它替换为0,代码如下:
df = df.replace({'WOE': {np.inf: 0, -np.inf: 0}})
5.计算IV值
df['IV'] = df['WOE'] * (df['坏样本%'] - df['好样本%'])
df
iv = df['IV'].sum()
print(iv)
整理上面计算WOE值和IV值的内容,完整代码如下所示:
1.构造数据
import pandas as pd
data = pd.DataFrame([[22,1],[25,1],[20,0],[35,0],[32,1],[38,0],[50,0],[46,1]], columns=['年龄', '是否违约'])
# 2.数据分箱
data_cut = pd.cut(data['年龄'], 3)
# 3.统计各个分箱样本总数、坏样本数和好样本数并汇总数据
# 统计总客户数
cut_group_all = data['是否违约'].groupby(data_cut).count()
# 统计违约客户
cut_y = data['是否违约'].groupby(data_cut).sum()
# 统计未违约客户
cut_n = cut_group_all - cut_y
# 汇总基础数据
df = pd.DataFrame() # 创建一个空DataFrame用来汇总数据
df['总数'] = cut_group_all
df['坏样本'] = cut_y
df['好样本'] = cut_n
# 4.统计坏样本%和好样本%
df['坏样本%'] = df['坏样本'] / df['坏样本'].sum()
df['好样本%'] = df['好样本'] / df['好样本'].sum()
# 5.计算WOE值
import numpy as np
df['WOE'] = np.log(df['坏样本%'] / df['好样本%'])
df = df.replace({'WOE': {np.inf: 0, -np.inf: 0}}) # 替换可能存在的无穷大
# 6.计算各个分箱的IV值
df['IV'] = df['WOE'] * (df['坏样本%'] - df['好样本%'])
# 7.汇总各个分箱的IV值,获得特征变量的IV值
iv = df['IV'].sum()
print(iv)