数据分箱(也称为离散分箱或分段)是一种数据预处理技术,用于减少次要观察误差的影响,是一种将多个连续值分组为较少数量的“分箱”的方法。
例如,例如我们有一组关于人年龄的数据,如下图所示:
现在我们希望将他们的年龄分组到更少的间隔中,可以通过设置一些条件来实现:
分箱的数据不一定必须是数字,它们可以是任何类型的值,如“狗”,“猫”,“仓鼠”等。 分箱也用于图像处理,通过将相邻像素组合成单个像素,它可用于减少数据量。
一般在建立分类模型时,需要对连续变量离散化,特征离散化后,模型会更稳定,降低了模型过拟合的风险。比如在建立申请评分卡模型时用logsitic作为基模型就需要对连续变量进行离散化,离散化通常采用分箱法。分箱的有以下重要性及其优势:
自底向上的(即基于合并的)数据离散化方法。它依赖于卡方检验:具有最小卡方值的相邻区间合并在一起,直到满足确定的停止准则。
基本思想:
对于精确的离散化,相对类频率在一个区间内应当完全一致。因此,如果两个相邻的区间具有非常类似的类分布,则这两个区间可以合并;否则,它们应当保持分开。而低卡方值表明它们具有相似的类分布。
这里需要注意初始化时需要对实例进行排序,在排序的基础上进行合并。
卡方阈值的确定:
根据显著性水平和自由度得到卡方值自由度比类别数量小1。例如:有3类,自由度为2,则90%置信度(10%显著性水平)下,卡方的值为4.6。
阈值的意义:
类别和属性独立时,有90%的可能性,计算得到的卡方值会小于4.6。 大于阈值4.6的卡方值就说明属性和类不是相互独立的,不能合并。如果阈值选的大,区间合并就会进行很多次,离散后的区间数量少、区间大。
注:
1、ChiMerge算法推荐使用0.90、0.95、0.99置信度,最大区间数取10到15之间.
2、也可以不考虑卡方阈值,此时可以考虑最小区间数或者最大区间数。指定区间数量的上限和下限,最多几个区间,最少几个区间。
3、对于类别型变量,需要分箱时需要按照某种方式进行排序。
def create_bins(lower_bound, width, quantity):
"""
创建等距分箱
"""
bins = []
for low in range(lower_bound,
lower_bound + quantity * width + 1, width):
bins.append((low, low + width))
return bins
bins = create_bins(lower_bound=50,
width=4,
quantity=10)
print(bins)
输出:
[(50, 54), (54, 58), (58, 62), (62, 66), (66, 70), (70, 74), (74, 78), (78, 82), (82, 86), (86, 90), (90, 94)]
给出一组数据,然后查找它们所属的分箱
def find_bin(value, bins):
"""
查找分箱
"""
for i in range(0, len(bins)):
if bins[i][0] <= value < bins[i][1]:
return i
return -1
from collections import Counter
weights_of_persons = [73.4, 69.3, 64.9, 75.6, 74.9, 80.3,
78.6, 84.1, 88.9, 90.3, 83.4, 69.3,
52.4, 58.3, 67.4, 74.0, 89.3, 63.4]
binned_weights = []
for value in weights_of_persons:
bin_index = find_bin(value, bins)
print(value, bin_index, bins[bin_index])
binned_weights.append(bin_index)
frequencies = Counter(binned_weights)
print(frequencies)
输出:
73.4 5 (70, 74)
69.3 4 (66, 70)
64.9 3 (62, 66)
75.6 6 (74, 78)
74.9 6 (74, 78)
80.3 7 (78, 82)
78.6 7 (78, 82)
84.1 8 (82, 86)
88.9 9 (86, 90)
90.3 10 (90, 94)
83.4 8 (82, 86)
69.3 4 (66, 70)
52.4 0 (50, 54)
58.3 2 (58, 62)
67.4 4 (66, 70)
74.0 6 (74, 78)
89.3 9 (86, 90)
63.4 3 (62, 66)
Counter({4: 3, 6: 3, 3: 2, 7: 2, 8: 2, 9: 2, 5: 1, 10: 1, 0: 1, 2: 1})
以上两种算法的弊端:比如,等宽区间划分,划分为5区间,最高工资为50000,则所有工资低于10000的人都被划分到同一区间。等频区间可能正好相反,所有工资高于50000的人都会被划分到50000这一区间中。这两种算法都忽略了实例所属的类型,落在正确区间里的偶然性很大。
reference:https://blog.csdn.net/Pylady/article/details/78882220
首先创建一个长度为20的,范围在30-100之间的学生分数的数组
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
score_list = np.random.randint(30, 100, size=20)
print(score_list)
[52 54 36 82 91 62 78 75 65 96 97 62 62 49 94 37 61 30 88 32]
然后我们再设置分箱:
bins=[0,59,70,80,100]
这就表示数据有0-59,59-70,70-80,80-100这几个等级。
下面把分箱和分数利用cut方法结合到一起。
score_cat = pd.cut(score_list, bins)
print(pd.value_counts(score_cat))
(0, 59] 8
(80, 100] 7
(59, 70] 3
(70, 80] 2