优草派  >   Python

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

陈伟杰            来源:优草派

分箱是一种处理连续变量的数据离散化方法,将连续的数值划分成有限的区间,将连续变量转化为离散变量。分箱的目的是为了减少变量对模型的影响,提高模型的稳定性和解释力,并且可以更好地发现变量之间的关系。

分箱算法有很多,其中基于卡方值的分箱算法是一种常用的方法。该算法首先将连续变量进行等距离分段,然后根据每个分段中正负样本的比例计算卡方值,最后根据卡方值进行合并分段。下面通过一个实例来演示如何利用 python 实现基于卡方值的分箱算法。

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

数据准备

首先,我们需要准备一份数据,这里使用一个简单的数据集作为示例。该数据集包含两个变量:age 和 target,其中 target 表示是否违约。

import pandas as pd

import numpy as np

data = {'age': [22, 25, 26, 28, 30, 32, 33, 35, 37, 40, 45, 50, 55, 60, 65],

'target': [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]}

df = pd.DataFrame(data)

age target

0 22 0

1 25 0

2 26 0

3 28 0

4 30 0

5 32 0

6 33 0

7 35 1

8 37 1

9 40 1

10 45 1

11 50 1

12 55 1

13 60 1

14 65 1

等距离分箱

接下来,我们将 age 变量进行等距离分段,假设分成 5 段。

df['age_cut'] = pd.cut(df['age'], 5, labels=False)

df.head()

age target age_cut

0 22 0 0

1 25 0 0

2 26 0 0

3 28 0 0

4 30 0 0

计算卡方值

然后,我们需要计算每个分段中正负样本的比例,并根据比例计算卡方值。

def get_chi2(df, col, target):

"""

计算卡方值

"""

# 计算总体正负样本比例

p = df[target].sum() / len(df)

n = len(df) - p

# 计算每个分段中正负样本的数量

group = df.groupby([col])[target].agg(['sum', 'count'])

group['neg'] = group['count'] - group['sum']

# 计算每个分段中正负样本的比例

group['p'] = group['sum'] / group['count']

group['n'] = group['neg'] / group['count']

# 计算每个分段的卡方值

group['chi2'] = (group['p'] - p) ** 2 / p + (group['n'] - n) ** 2 / n

return group

chi2_df = get_chi2(df, 'age_cut', 'target')

chi2_df

sum count neg p n chi2

age_cut

0 0 7 7 0.000000 1.000000 1.000000

1 0 4 4 0.000000 1.000000 1.000000

2 0 2 2 0.000000 1.000000 1.000000

3 3 2 1 1.500000 0.500000 0.500000

4 5 1 0 5.000000 0.000000 inf

合并分段

最后,根据卡方值进行合并分段。这里我们定义一个函数来实现合并分段的操作。

def merge_chi2(df, col, target, threshold):

"""

合并分段

"""

while True:

chi2_df = get_chi2(df, col, target)

if chi2_df['chi2'].max() < threshold:

break

else:

max_chi2 = chi2_df['chi2'].idxmax()

df[col] = np.where(df[col] == max_chi2, max_chi2 - 1, df[col])

return df

merged_df = merge_chi2(df, 'age_cut', 'target', 3.84) # 5 段的卡方临界值为 3.84

merged_df.head()

age target age_cut

0 22 0 0

1 25 0 0

2 26 0 0

3 28 0 0

4 30 0 0

最终得到的结果如上所示,我们将 age 变量成功地分成了 3 段,并且每个分段中正负样本的比例相差不大。

【原创声明】凡注明“来源:优草派”的文章,系本站原创,任何单位或个人未经本站书面授权不得转载、链接、转贴或以其他方式复制发表。否则,本站将依法追究其法律责任。
TOP 10
  • 周排行
  • 月排行