2025年卡方分箱及代码实现

卡方分箱及代码实现本文先从统计基础的卡方分布 卡方检验说起 之后再到卡方分箱的理解就比较容易 最后是利用 Python 如何实现卡方分箱 1 卡方分布 定义 设随机变量 X 1 X 1 X 1 X

大家好,我是讯享网,很高兴认识大家。

本文先从统计基础的卡方分布、卡方检验说起,之后再到卡方分箱的理解就比较容易,最后是利用Python如何实现卡方分箱。

1.卡方分布

  1. 定义: 设随机变量 X 1 X_1 X1 X 2 X_2 X2 X 3 X_3 X3,…, X n X_n Xn相互独立,且 X i X_i Xi(i=1,2,3,…,n)服从标准正态分布N(0,1),则他们的平方和 ∑ X i 2 \sum X_i^2 Xi2服从自由度为n的 χ 2 \chi^2 χ2分布。
  2. χ 2 \chi^2 χ2分布示意图
    卡方分布示意图在这里插入图片描述
    讯享网
  • 如上图,df自由度越小,分布就越向左倾斜,随着自由度逐渐增大, χ 2 \chi^2 χ2分布趋近于正态分布。

2.卡方统计量

χ 2 \chi^2 χ2统计量:

χ 2 = ∑ ( f 0 − f e ) 2 f e \chi^2=\sum\frac{(f_0-f_e)^2}{f_e} χ2=fe(f0fe)2

f 0 f_0 f0表示观测值频数, f e f_e fe表示期望值频数

  • χ 2 \chi^2 χ2统计量描述了观察值与期望值的接近程度,两者越接近,即 ( f 0 − f e ) (f_0-f_e) (f0fe)的绝对值越小,计算的 χ 2 \chi^2 χ2值就越小;反之,则 χ 2 \chi^2 χ2越大。

3.卡方检验

  • χ 2 \chi^2 χ2检验是对分类数据的频数进行分析的统计方法;用于分析分类变量与分类变量之间的关系(相关程度)
  • 通过对 χ 2 \chi^2 χ2的计算结果与 χ 2 \chi^2 χ2分布中的临界值进行比较,做出是否拒绝原假设的统计决策。
  • χ 2 \chi^2 χ2检验分为拟合优度检验和独立性检验

3.1 拟合优度检验

  • 定义:拟合优度检验是对一个分类变量的检验,即根据总体的分布情况,计算出分类变量中各分类的期望频数,与分布的观测频数进行对比,判断期望频数与观察频数是否有显著差异。
  • 举例:泰坦尼克号例子中,我们关注存活情况与性别是否有关系。
    船上共有2208人,其中男性1738人,女性470人;幸存者718人,其中男性374人女性344人,以 α \alpha α=0.1的显著性水平检验存活状况是否与性别相关。
    解:
    1、提出假设:
    H 0 H_0 H0:观察频数与期望频数一致
    H 1 H_1 H1:观察频数与期望频数不一致
    2、根据观察频数计算期望频数:
    总体存活率为718/2208=0.325,如果是否活下与性别无关,那么1738名男性中应该存活的人数为17380.325=565人,在470位女性中应存活4700.325=153人。故565和153就是期望频数,实际存活数就是观察频数。
    3、计算卡方统计量:
    在这里插入图片描述
    4、根据自由度和显著性水平,查找卡方分布表临界值,并与上一步 χ 2 \chi^2 χ2值进行比较,做出接受或拒接原假设的决策。
    自由度df=R-1=1,R为分类变量类型的个数。 显著性水平为0.1, 查表得 χ 0.1 2 ( 1 ) \chi^2_{0.1}(1) χ0.12(1)=2.706;
    所以 χ 2 \chi^2 χ2远大于 χ 0.1 2 ( 1 ) \chi^2_{0.1}(1) χ0.12(1),拒绝 H 0 H_0 H0,接受 H 1 H_1 H1,说明存活情况与性别有关。

3.2 列联分析:独立性检验

  • 定义:独立性检验对两个分类变量的检验,分析过程通过列联表(contingency table)方式呈现,实际就转换为分析列联表中行变量与列变量是否相互独立(或有关联)。
  • 举例:一种原料来自三个不同地区,原料质量又被分成三个不同等级,从这批原料中随机抽取500个检验,如下表;那么检验地区和等级直接是否存在依赖关系。
    在这里插入图片描述
    解:
    1、提出假设:
    H 0 H_0 H0:地区和原料等级之间是独立的
    H 1 H_1 H1:地区和原料等级之间是不独立的(存在依赖关系)

    2、根据观察频数计算期望频数:

    • 以列联表表第一行第一列(甲,一级)为例,甲地区的合计为140,用140/500作为甲地区的原料比例估计值;一级原料的合计为162,用162/500作为一级原料的比例的估计值。如果地区与原料等级独立,那么第一行第一列单元格的期望值比例为:
      (140/500)x(162/500)= 0.09072,故相应的频数为 0.09072 x 500 = 45.36。
  • 推广,可采用以下方式计算任一单元格的期望频数:

    f e f_e fe = R T n \frac{RT}{n} nRT * C T n \frac{CT}{n} nCT * n n n = C T ∗ R T n \frac{CT *RT}{n} nCTRT

    RT为给定单元格所在行的合计,CT为给定单元格所在列的统计,n为观测值的个数,即样本量。

    3. 计算卡方统计量
    在这里插入图片描述
    4、根据自由度和显著性水平,查找卡方分布表临界值,并与上一步 χ 2 \chi^2 χ2值进行比较,做出接受或拒接原假设的决策。
    自由度df=(R-1)(C-1)=4,显著性水平取0.05,查看可知 χ 0.05 2 ( 4 ) \chi^2_{0.05}(4) χ0.052(4)=9.488;
    所以 χ 2 \chi^2 χ2远大于 χ 0.05 2 ( 4 ) \chi^2_{0.05}(4) χ0.052(4),拒绝 H 0 H_0 H0,接受 H 1 H_1 H1,说明地区和原料等级存在依赖关系,即原料等级受地区的影响。

4. 卡方分箱原理及流程

卡方分箱是基于卡方检验中第二种列联独立性检验原理进行分箱。

以下是截取卡方分箱论文中分箱的算法:
在这里插入图片描述
在这里插入图片描述

  1. 上诉算法理解分为初始化和自底向上的合并过程
    • 初始化:首先根据连续变量的值的大小排序,进行初始的离散处理
    • 合并:
      箱子合并过程分为两个步骤,连续重复进行:
      1. 计算每个相邻箱子的 χ 2 \chi^2 χ2
      2. 对低卡方值的相邻箱子进行合并
      (根据卡方检验原理可知卡方值越低,表明两个类别越独立,相互影响的程度越小;或者另一种理解是两箱分布相似,可以进行合并。)

      合并停止条件:

      • 直到所有相邻箱子的 χ 2 \chi^2 χ2值大于等于设置的 χ 2 \chi^2 χ2阈值
        (根据自由度和显著性水平选取合适的 χ 2 \chi^2 χ2阈值;自由度则是根据数据能够确定的为(R-1)x(C-1),因为都是计算相邻两箱的,故R=2;C也可根据数据情况确定。显著性水平推荐选择0.1,0.05,0.01。)
      • 或者,箱子数量达到预先设置的数量
        (可以设置最小分箱数和最大分箱数,推荐最大分箱数在10-15间)
  2. 公式的理解
    在这里插入图片描述
    与卡方检验中列联独立性检验的 χ 2 \chi^2 χ2值的计算是相同的
    A i j A_{ij} Aij就是 f 0 f_0 f0 E i j E_{ij} Eij就是 f e f_e fe
    k就是列的分类变量类型个数
    m=2(只计算行相邻两箱)

具体也可看下面示例:
ps:注意每两箱计算时列的合计数是不同的,只使用两箱的列合计数,而不是全部的列合计数,行合计数不受影响。样本数量也只使用两箱的样本数量。
在这里插入图片描述
在这里插入图片描述

5.利用Python实现卡方分箱

def chimerge(data,col,target,n=20,alpha=0.05,max_groups=8): ''' data: 输入的pandas DataFrame数据集 col: 需要分箱得连续型变量名 target: Y值 n:初始化分箱的个数,一般选取比较大的值(使用的是等距分箱) alpha:卡方分布的显著性水平 max_groups: 最大分箱个数 ''' # 先进行初略的等距分箱 df = data[[col,target]] df['cut'],bins = pd.cut(df[col],bins=n,retbins=True,right=False) # right=False,使得区间为左闭右开如[0,10),与下面的cutoff相一致 freq_tab = pd.crosstab(df['cut'],df[target],dropna=False) # 注意要添加dropna=False,否则全为0的组就不显示 freq = freq_tab.values # 转换为array数组 cutoff = bins[:-1] # 分组区间是左闭右开的,如cutoffs = [1,2,3],则表示区间 [1,2) , [2,3) ,[3,3+)。 # 以下代码确保每一箱中都有target正负样本 # 这样做的好处一是后续如果计算WOE时有这个需要,二是也能保证计算的期望频数fe不为0。 for i in range(n): # 如果第一箱没有包含正样本或负样本,则向下一组合并 # 但即使原来第一箱和第二进行和合并,还是不能保证新的第一箱都包含正负样本,故使用continue跳出本次循环,开始下一次循环 if 0 in freq[0]: freq[0] = freq[0] + freq[1] freq = np.delete(freq,1,0) cutoff = np.delete(cutoff,1,0) continue # 经过上面代码确保第一箱都包含正负样本,则判断之后的每箱,是否都包含正负样本,如果不包含,则向前一箱合并 for i in range(1,len(freq)): if 0 in freq[i]: freq[i-1] = freq[i] + freq[i-1] freq = np.delete(freq,i,0) cutoff = np.delete(cutoff,i,0) break else: break # 计算相邻箱的卡方值 threshold = scipy.stats.chi2.isf(alpha,freq.shape[-1]) # 卡方阈值根据显著性水平和自由度设置 while len(freq) > max_groups: # 先根据设定的最大分箱数,合并最小的卡方值 chi_vs=[] for i in range(len(freq)-1): chi_v = scipy.stats.chi2_contingency(freq[i:i+2])[0] chi_vs.append(chi_v) i = chi_vs.index(min(chi_vs)) freq[i] = freq[i] + freq[i+1] freq = np.delete(freq,i+1,0) cutoff = np.delete(cutoff,i+1,0) # 按照预先设定的分箱数合并完毕后,如果发现最小卡方值还有低于卡方阈值的再接着合并 while True: for i in range(len(freq)-1): chi_vs=[] chi_v = scipy.stats.chi2_contingency(freq[i:i+2])[0] chi_vs.append(chi_v) if min(chi_vs) < threshold: i = chi_vs.index(min(chi_vs)) freq[i] = freq[i] + freq[i+1] freq = np.delete(freq,i+1,0) cutoff = np.delete(cutoff,i+1,0) continue else: break return cutoff,freq 

讯享网
讯享网# 将变量的值转换为相应的组 def value_to_group(x,cutoff): ''' x 是需要划分组的标量值 cutoff 是根据上述chimerge函数返回的箱边值 ''' cutoff.sort() # 小于最小值的异常值也都放入第一组 if x < cutoff[0]: return 'group-1' for i in range(1,len(cutoff)): if cutoff[i-1] <= x < cutoff[i]: return 'group-{}'.format(i) # 最后一组也包含非常大的异常值 if x >= cutoff[len(cutoff)-1]: return 'group-{}'.format(len(cutoff))

以上,如有错误,还请大家指教。

【参考资料】
1.贾俊平统计学第七版
2.卡方分箱论文
3.菜菜的sklearn课堂
4.Python评分卡建模—卡方分箱(2)之代码实现
5.python中break,continue,pass,else的用法和区别详解

小讯
上一篇 2025-02-16 14:18
下一篇 2025-03-13 08:05

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/65354.html