自动分箱的代码实现(基于卡方)

def mc_chiMerge_final(df,var,target,max_groups=None,threshold=None):
  """
    df: 数据集
    var: 变量
    target: 标签
    max_groups: 最大分箱个数
    threshold: 卡方阈值
    """
    import numpy as np
    import pandas as pd

    
    def mc_chi2(arr): 
        #arr:频数统计表
        assert(arr.ndim==2)
        #计算每行频数
        R_N = arr.sum(axis=1)
        #每列总频数
        C_N = arr.sum(axis=0)
        #总频数
        N = arr.sum()
        #计算期望频数C_i*R_j/N
        E = np.ones(arr.shape) * C_N /N
        E = (E.T * R_N).T
        square = (arr-E)**2/E
        #期望频数为0时,无法作为除数,不计入卡方值
        square[E==0] = 0
        #卡方值
        v = square.sum()
        return v

    freq_tab = pd.crosstab(df[var],df[target])
    #转成numpy数组用于计算
    freq = freq_tab.values
    #初始分组切分点,每个变量值都是切分点;每组中只包含一个变量值.    
    #分组区间是左闭右开的,如cutoffs = [1,2,3],则表示区间 [1,2) , [2,3) ,[3,3+)
    cutoffs = freq_tab.index.values
    #如果没有指定最大分组
    if max_groups is None:
        #如果没有指定卡方阈值,就以95%的置信度(自由度为类数目-1)设定阈值。
        if threshold is None:
            #类数目
            cls_num = freq.shape[-1]
            threshold = mc_chi2.isf(0.05,df= cls_num - 1)
            
    while True:
        minvalue = None
        minidx = None
        #从第1组开始,依次取两组计算卡方值,并判断是否小于当前最小卡方值
        for i in range(len(freq) - 1):
            v = mc_chi2(freq[i:i+2])
            if minvalue is None or minvalue>v: #小于当前最小卡方值,更新最小值
                minvalue = v
                minidx = i
                
        #如果最小卡方值小于阈值,则合并最小卡方值的相邻两组,并继续循环
        if(max_groups is not None and max_groups

你可能感兴趣的:(学习笔记)