什么叫分箱?

连续变量的离散化处理。例如年龄:从1、2、3、4……100变成“1~20”、“21~30”差不多这个样子。

问题场景(为什么要分箱):

不论是做业务分析还是建模前的特征工程,经常会遇到一个问题,连续变量需要分箱。且分箱会有一个诉求:分出来的组,对于目标指标(比如转化率)差异最大。

业务分析中这样做的目的在于:一些连续变量对于最终结果指标的影响程度有更好的可解释性。

比如客户的年龄与转化率相关性可能0.3~0.5,有一定的相关性,这样的结果很难下结论,也很难进行下一步推进。

但如果进行了分箱,比如:我们将客户分成了25岁以下,25~35岁,和35岁以上,可以发现,年龄较大的群体转化率更高,可以告诉业务方我们的产品更能吸引什么年龄段的用户。业务更能接受分了群的用户群体,而不是1~100的精确年龄。

而特征工程中试用分箱主要还是增强模型的泛化能力,避免过拟。

难点:

很直白的问题,怎么分才最合适?

解题思路:

分箱的方法论网上能搜到很多,分为有监督和无监督,这里不展开。

这里主要分享我整合的一个分箱函数。调用可以直接完成分箱。

代码与解释:



#系统
import os

#可视化包
import seaborn as sns
from IPython.display import Image
import pydotplus 
import matplotlib.pyplot as plt
sns.set()
os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'
plt.rcParams['font.sans-serif'] = ['simhei']
plt.rcParams['font.serif'] = ['simhei']
sns.set_style("darkgrid",{"font.sans-serif":['simhei','Droid Sans Fallback']})

#数学包
from scipy import stats
import pandas as pd
import numpy as np
#机器学习
from sklearn.ensemble import RandomForestRegressor

#数据--天池新手赛-二手车价格预测训练集
df_0=pd.read_csv(r'C:UsersAdminDownloadsused_car_train_20200313.csv',sep=' ')
df_0.head()

#抽样一部分作为演示
df_1=df_0.sample(n=500)
df_1.dropna(inplace=True)



完成加载包和数据的准备工作



def my_binsByDTR(X,y,n=3,min_samples_percent=0.2):
    if n>=2:
        #回归树输出多分类
        dtr=DecisionTreeRegressor(max_leaf_nodes=n,min_samples_leaf=int(min_samples_percent*len(X)))
        dtr.fit(X,y)
        pred=dtr.predict(X)
        
        #标签映射
        l1=np.sort(np.unique(pred))
        l2=[]
        for x in range(0,n):
            l2.append("cata_"+str(x+1))
        df_mapping=pd.DataFrame({"cata":l1,"label":l2})
        df_input=X
        df_input.columns=['x']
        df_input['y']=y
        df_input['cata']=pred
        df_input=pd.merge(df_input,df_mapping,on="cata",how="left")

        #打印统计量-需要返回可修改
        print(df_input.groupby(['label'])['y'].describe())
        
        #打印分箱阈值
        print("threadhold:",np.sort(dtr.tree_.threshold[0:n-1]))
        
        #可视化
        plt.figure(figsize=(12, 6))
        sns.boxplot(x="label", y="y",data=df_input,order=df_mapping.label)#,fliersize=0

        return df_input['label']
    else:
        print('error')

df_1['bin']=my_binsByDTR(df_1[['power']].copy(),df_1['price'],n=3)



输入:

X:Dataframe对象,此处只传需要分箱的那列变量即可。

y:目标指标,比如转化率。

输出:

返回分箱后的标签。可以在原数据集增加一列直接接收。

打印:

  1. 打印出分组后的描述统计(各组的计数、目标指标的均值等)。
  2. 打印分箱阈值。
  3. 分组后的箱线图,可视化组间差异。

效果图:




python实现woe分箱 python分箱代码_ci