Package: binning
binning and calculate woe，iv valuebinning: better for ai engineer to get bin result. Now it supports distance, frequency, enumerate, chi-square, custom bin. it support parallel compute when numbers of features are greater than one hundred or the number of samples are greater than one million, it has better performance.| when the distribution type of feature is "CONTINUOUS", we can use distance, frequency, chi-square and custom bin. others, we can use enumerate, chi-square and custom bin| we can calculate woe and iv value by the bin result特征分箱及 WOE&IV 计算特征分箱，目前支持等距、等频、枚举、卡方、自定义分箱分箱方式连续特征等距，等频，卡方，自定义离散特征枚举，卡方，自定义合并分箱根据不同的特征类型进行不同合并分箱，同时支持不进行合并分箱合并原则连续特征合并分箱根据最小样本量离散特征合并分箱根据最小样本量，正负样本比率等频和枚举分箱方式不进行合并分箱Quick StartInstallationpipinstallbinningExample: bins dictimportpandasaspdfrombinningimport__version__frombinning.binprocessingimportBinProcessing# version, 获取版本print(__version__)# custom log function, 自定义日志函数deflog_fun(mess):print(f"打印日志信息：{mess}")# parallel, 是否并行parallel=False# distribution: 1 is continuous, 0 is discrete# distance bin, 等距分箱data={"feature":[1.1,2.1,3.1,4.1,5.1,6.1,7.1,8.1,9.1,10.1],"label":[1,1,0,0,1,1,1,0,0,0]}df=pd.DataFrame(data)features={"feature":1}kw_params={"label":"label","bins":3}bp=BinProcessing("DISTANCE_BIN",features,df,parallel,log_fun,**kw_params)bins_dict=bp.get_bins_dict()print(bins_dict)# frequency bin, 等频分箱data={"feature":[1.1,2.1,3.1,4.1,5.1,6.1,7.1,8.1,9.1,10.1],"label":[1,1,0,0,1,1,1,0,0,0]}df=pd.DataFrame(data)features={"feature":1}kw_params={"label":"label","q":3,"min_samples":10}bp=BinProcessing("FREQUENCY_BIN",features,df,parallel,log_fun,**kw_params)bins_dict=bp.get_bins_dict()print(bins_dict)# enumerate bin, 枚举分箱data={"feature":["A","B","A","B","C","A","C","B","A","C"],"label":[1,1,0,0,1,1,1,0,0,0]}df=pd.DataFrame(data)features={"feature":0}kw_params={"label":"label"}bp=BinProcessing("ENUMERATE_BIN",features,df,parallel,log_fun,**kw_params)bins_dict=bp.get_bins_dict()print(bins_dict)# chi-square bin, 卡方分箱data={"feature":["A","B","A","B","C","A","C","B","A","C"],"feature2":[1.1,2.1,3.1,4.1,5.1,6.1,7.1,8.1,9.1,10.1],"label":[1,1,0,0,1,1,1,0,0,0]}df=pd.DataFrame(data)features={"feature":0,"feature2":1}kw_params={"label":"label"}# 连续特征参数kw_params["con_bins"]=3kw_params["con_min_samples"]=5kw_params["con_threshold"]=3.8# 离散特征参数kw_params["cat_bins"]=2kw_params["cat_min_samples"]=5kw_params["cat_threshold"]=3.7bp=BinProcessing("CHIMERGE_BIN",features,df,parallel,log_fun,**kw_params)bins_dict=bp.get_bins_dict()print(bins_dict)# custome bin, 自定义分箱data={"feature":["A","B","A","B","C","A","C","B","A","C"],"feature2":[1.1,2.1,3.1,4.1,5.1,6.1,7.1,8.1,9.1,10.1],"label":[1,1,0,0,1,1,1,0,0,0]}df=pd.DataFrame(data)features={"feature":0,"feature2":1}kw_params={"label":"label"}# 连续特征参数kw_params["con_param"]="2.1,4.1"kw_params["con_min_samples"]=5# 离散特征参数kw_params["cat_param"]=["A","C"]kw_params["cat_min_samples"]=3bp=BinProcessing("CUSTOM_BIN",features,df,parallel,log_fun,**kw_params)bins_dict=bp.get_bins_dict()print(bins_dict)Example: feature dict and woe, iv valueimportpandasaspdfrombinning.binprocessingimportBinProcessingfrombinning.calprocessingimportCalProcessingdefget_features_dict(df:pd.DataFrame,features:Dict[str,int])->Dict[str,Any]:"""get features dictArgs:df (pd.DataFrame): 数据源features (Dict[str,int]): 特征集Returns:Dict[str,Any]: 特征字典"""ret_features_dict={}con_features={k:vfork,vinfeatures.items()ifv==1}cat_features={k:vfork,vinfeatures.items()ifv==0}ifself.con_cut==BinType.DISTINCE_BIN.valueandcon_features:kw_params={"label":self.label_b,"bins":self.con_group,"min_samples":self.con_cut_param["minSampleNum"]}bp=BinProcessing("DISTANCE_BIN",con_features,df,parallel,self._log,**kw_params)ret_dict=bp.get_features_dict()ret_features_dict.update(ret_dict)ifself.con_cut==BinType.FREQUENCY_BIN.valueandcon_features:kw_params={"label":self.label_b,"q":self.con_group}bp=BinProcessing("FREQUENCY_BIN",con_features,df,parallel,self._log,**kw_params)ret_dict=bp.get_features_dict()ret_features_dict.update(ret_dict)ifself.cat_cut==BinType.DISCRE_ENUM_BIN.valueandcat_features:kw_params={"label":self.label_b}bp=BinProcessing("ENUMERATE_BIN",cat_features,df,parallel,self._log,**kw_params)ret_dict=bp.get_features_dict()ret_features_dict.update(ret_dict)ifself.is_con_feature_chi2orself.is_cat_feature_chi2:chi_features=self.get_chi2_features_dict(features,con_features,cat_features)kw_params={"label":self.label_b}ifself.is_con_feature_chi2andself.con_cut_param:kw_params["con_bins"]=self.con_cut_param["maxBinNum"]kw_params["con_min_samples"]=self.con_cut_param["minSampleNum"]kw_params["con_threshold"]=self.con_cut_param["threshold"]ifself.is_cat_feature_chi2andself.cat_cut_param:kw_params["cat_bins"]=self.cat_cut_param["maxBinNum"]kw_params["cat_min_samples"]=self.cat_cut_param["minSampleNum"]kw_params["cat_threshold"]=self.cat_cut_param["threshold"]bp=BinProcessing("CHIMERGE_BIN",chi_features,df,parallel,self._log,**kw_params)ret_dict=bp.get_features_dict()ret_features_dict.update(ret_dict)ifself.single_cut==BinType.CUSTOM_BIN.value:kw_params={"label":self.label_b}kw_params["con_param"]=self.single_bin_param.get('userDefineParam')kw_params["con_min_samples"]=self.min_sample_numkw_params["cat_param"]=self.single_bin_param.get('discreteDefineParam')kw_params["cat_min_samples"]=self.min_sample_numbp=BinProcessing("CUSTOM_BIN",features,df,parallel,self._log,**kw_params)ret_dict=bp.get_features_dict()ret_features_dict.update(ret_dict)defget_woe_iv(con_bin_type:str,cat_bin_type:str,features:Dict[str,int],features_dict:Dict[str,Any],bin_params:Dict[str,Any],min_samples:Dict[str,int],log:Callable)->Tuple[Dict[str,Any],pd.Series]:"""get woe, iv valueArgs:con_bin_type (str): 连续特征分箱类型cat_bin_type (str): 离散特征分箱类型features (Dict[str,int]): 特征字典features_dict (Dict[str,Any]): 特征信息bin_params (Dict[str,Any]): 分箱参数min_samples (Dict[str,int]): 最小样本量log (Callable): 日志函数Returns:Tuple[Dict[str,Any], pd.Series]: woe, iv"""kw_params={"con_bin_type":con_bin_type,"cat_bin_type":cat_bin_type,"features":features,"features_dict":features_dict,"bin_params":bin_params}ifmin_samples.get("con_min_samples"):kw_params["con_min_samples"]=min_samples["con_min_samples"]ifmin_samples.get("cat_min_samples"):kw_params["cat_min_samples"]=min_samples["cat_min_samples"]cp=CalProcessing("WOEIV",log,**kw_params)woe,iv=cp.get_cal_val()return(woe,iv)