Python版scorecardpy库woebin函数使用

scorecardpy 是一款专门用于评分卡模型开发的 Python 库,由谢士晨博士开发,该软件包是R软件包评分卡的Python版本。量级较轻,依赖更少,旨在简化传统信用风险计分卡模型的开发过程,使这些模型的构建更加高效且易于操作。

本文主要讲解 scorecardpy 库的变量分箱 woebin 函数的使用,让你了解函数中每个入参的使用姿势,快速高效地进行评分卡建模分析。分箱的原理在之前的 sklearn-逻辑回归-制作评分卡 中有讲过,可自行跳转了解。

目录

scorecardpy安装

scorecardpy提供的功能

woebin 函数定义

woebin 函数参数解析

参数1:dt

参数2:y

check_y 函数对标签值进行检测

代码解析

参数3:x

参数4:var_skip

参数5:breaks_list

参数6:special_values

参数7:count_distr_limit

参数8:stop_limit

IV增长率

卡方值

参数9:bin_num_limit

参数10:positive

positive 参数的设置

参数11:no_cores

参数12:print_step

参数取值详解

使用建议

参数13:method

支持的分箱方法

1、tree(决策树分箱)‌:

‌2、chimerge(卡方分箱)‌:

使用建议

参数14:ignore_const_cols

参数15:ignore_datetime_cols

参数16:check_cate_num

参数17:replace_blank

参数18:save_breaks_list


scorecardpy安装

使用 Python 包管理器 pip 进行安装

pip install scorecardpy

scorecardpy提供的功能

为了使评分卡建模流程更加便捷,scorecardpy 库对建模过程中的关键步骤都封装好了函数,在不同环节可以调用不同的函数

  • 数据集划分‌:通过split_df函数将数据集分割成训练集和测试集‌
  • 变量筛选‌:使用var_filter函数根据变量的缺失率、IV值、同值性等因素进行筛选
  • 变量分箱‌:提供woebin函数进行变量分箱,并可以生成分箱的可视化图表‌
  • 评分转换‌:使用scorecard函数进行评分转换‌
  • 效果评估‌:包括性能评估(perf_eva)和PSI(Population Stability Index)评估(perf_psi)‌

woebin 函数定义

def woebin(dt, y, x=None, var_skip=None, breaks_list=None, special_values=None, stop_limit=0.1, count_distr_limit=0.05, bin_num_limit=8, # min_perc_fine_bin=0.02, min_perc_coarse_bin=0.05, max_num_bin=8, positive="bad|1", no_cores=None, print_step=0, method="tree",ignore_const_cols=True, ignore_datetime_cols=True, check_cate_num=True, replace_blank=True, save_breaks_list=None, **kwargs):pass

woebin 函数适用于对特征进行分箱(bining)和权重证据转换(weight of evidence)的工具,它使用决策树分箱或者卡方分箱的方法对变量进行最佳分箱。

默认 woe 计算是 ln(Distr_Bad_i/Distr_Good_i),如果需要实现 ln(Distr_Good_i/Distr_Bad_i),需要将入参 positive 设置为想反的值,比如 0 或者 'good'。

woebin 函数参数解析

参数1:dt

类型是 pandas.DataFrame,包含要分箱的特征和标签变量 y 的 DataFrame

参数2:y

标签值的变量名称

传入的 dt 中,标签 y 列的取值不能有空的情况,如果检测到空,对应的行将会被删除,同时会提示 “There are NaNs in \'{}\' column”

    # remove na in yif dat[y].isnull().any():warnings.warn("There are NaNs in \'{}\' column. The rows with NaN in \'{}\' were removed from dat.".format(y,y))dat = dat.dropna(subset=[y])# dat = dat[pd.notna(dat[y])]

check_y 函数对标签值进行检测

check_y() 函数会对传入数据的 y 值进行检测,确保都是合理的,入参包含 dat, y, positive.

代码解析
def check_y(dat, y, positive):""":param dat: 数据集,pd.DataFrame 类型:param y: 标签y列名,string 类型,或者只有1个元素的 list 类型:param positive: 目标变量,string 类型:return: 数据集 dat"""positive = str(positive)# 数据集 dat 必须属于 pd.DataFrame 类型数据,且至少有2列,(一列特征,一列标签)if not isinstance(dat, pd.DataFrame):raise Exception("Incorrect inputs; dat should be a DataFrame.")elif dat.shape[1] <= 1:raise Exception("Incorrect inputs; dat should be a DataFrame with at least two columns.")# 如果 y 入参是 string 类型,在这里会被处理成只有1个元素的 list 类型数据y = str_to_list(y)# y 入参必须是只有1个元素,即一个数据集只能有一个标签列if len(y) != 1:raise Exception("Incorrect inputs; the length of y should be one")y = y[0]# y 标签列必须出现在数据集中if y not in dat.columns:raise Exception("Incorrect inputs; there is no \'{}\' column in dat.".format(y))# 如果有数据的标签取值为空,则该数据会被删除,不参与分箱评分if dat[y].isnull().any():warnings.warn("There are NaNs in \'{}\' column. The rows with NaN in \'{}\' were removed from dat.".format(y, y))dat = dat.dropna(subset=[y])# y 列数据转换成 int 类型数据if is_numeric_dtype(dat[y]):dat.loc[:, y] = dat[y].apply(lambda x: x if pd.isnull(x) else int(x))  # dat[y].astype(int)# y 的取值枚举必须是2中,否则抛出异常unique_y = np.unique(dat[y].values)if len(unique_y) == 2:# unique_y 存储了y取值的枚举,  positive 传值必须有一个值属于 unique_y 的某一个枚举# re.search() 函数第一个入参是正则表达式,第二个入参是要搜索的字符串# positive 默认值为 'bad|1',表示搜索字符串中的 "bad" 或 "1"。# 假如 unique_y 取值为 [0, 1],positive取默认值,if 条件即判断 True 是否包含在[False, True] 中if True in [bool(re.search(positive, str(v))) for v in unique_y]:y1 = dat[y]# re.split() 函数第一个入参是分隔符,第二个入参是字符串,代表使用分隔符将字符串分成一个列表# 因为 '|'是特殊字符,代表'或',因此前面要加转义字符'\'# lambda 接收一个 dat[y] 中的取值,判断这个取值是否出现在 positive 列表中,出现则为1,否则为0y2 = dat[y].apply(lambda x: 1 if str(x) in re.split('\|', positive) else 0)# y1 和 y2 两个Series对象中的每个对应元素是否不相等。# 如果至少有一个元素不相等,.any()方法会返回True;如果所有元素都相等,则返回Falseif (y1 != y2).any():# 如果有不相等的,则将 y2 赋值给 dat[y] 列# loc() 函数接受两个参数:第一个参数是行的选择器,第二个参数是列的选择器# [:, y]:这是.loc[]属性中的选择器参数。冒号:表示选择所有的行,而y表示选择名为y的列dat.loc[:, y] = y2  # dat[y] = y2warnings.warn("The positive value in \"{}\" was replaced by 1 and negative value by 0.".format(y))else:raise Exception("Incorrect inputs; the positive value in \"{}\" is not specified".format(y))else:raise Exception("Incorrect inputs; the length of unique values in y column \'{}\' != 2.".format(y))return dat

参数3:x

要分箱的特征列表,默认值是 None,如果该参数不传,将会默认 dt 中所有的除了y的列,都会参与分箱

参数4:var_skip

不参与分箱的特征列表,如果传入的是 string 类型,会自动转换成一个元素的 list 类型,并参与分箱特征的排除

参数5:breaks_list

分箱的边界值,是个 list 类型,默认一般是 None,如果该参数传入了值,则会根据传入的边界值进行分箱。假设传入的是 [0,10,20,30],使用左开右闭进行分箱,则会被分成 4 个箱子,即 (0,10],(10,20],(20,30],(30,+∞)

参数6:special_values

特殊值列表,默认是 None。如果传入该参数,那么取值在该参数列表中的元素,将会被分到独立的箱子中

假设传入 [-90,-9999],那个取值为-90,-9999的都会在一个特殊箱子里

参数7:count_distr_limit

每个箱内的样本数量占总样本数量的最小占比,默认值是 0.05,即最小占比 5%

该参数可以确保分箱结果更加合理和实用,特别是在要处理不平衡数据集或需要严格控制复杂度时

通过限制每个箱内的最小样本数,可以减少过拟合的风险,并提高模型在新数据上的泛化能力

需要注意的是,该参数的具体行为和效果可能受到其它参数(如分箱方法,分箱数量等)的影响,在使用时需要合理设置

参数8:stop_limit

控制分箱停止条件的参数,当统计量(比如IV增长率,卡方值)的增长率小于设置的 stop_limit 参数时,停止继续分箱,取值范围是 0-0.5,默认值是 0.1

该参数主要用于决定何时停止进一步的分箱操作,以避免过拟合或生成过多不必要的箱

该参数默认值设置为0.1,是一个比较小的数值,这意味着只有当统计量的增长率显著时,分箱才会继续。通过调整 stop_limit 的值,用户可以在分箱的数量和模型的复杂度之间找到平衡。

需要注意的是,该参数只是控制分箱停止条件的参数之一,在使用时需要合理结合设置,以确保分箱既有效又高效。

IV增长率

如果 woebin 函数使用信息值(IV)作为分箱的依据,stop_limit 可以设定为一个阈值,当相邻两次分箱后IV值的增长率小于这个阈值时,分箱停止

卡方值

在一些实现中,stop_limit 也可能与卡方值相关。当卡方值小于某个基于 stop_limit 计算出的临界值时,分箱也会停止

参数9:bin_num_limit

整数类型,可以分的最大箱子数量,默认值是 8

该参数是限制分箱算法可以生成的最大箱子数量,从而避免过度分箱导致的模型复杂度过高或数据过拟合问题。

当 woebin 函数对变量进行分箱时,它会考虑这个限制,并尝试在不超过 bin_num_limit 设定的箱数的前提下,找到最优的分箱方案

  • 如果 bin_num_limit 设定为一个较小的值,分箱算法会倾向于生成较少的、包含较多样本的箱,这可能会简化模型并减少过拟合的风险。

  • 如果 bin_num_limit 设定为一个较大的值,分箱算法则有更多的自由度来生成更多的、包含较少样本的箱,这可能会提高模型的精细度,但同时也可能增加模型的复杂度和过拟合的风险

在使用 bin_num_limit 参数时,需要根据具体的数据集和建模需求来选择合适的值。如果数据集较大且变量分布复杂,可能需要更多的箱来捕捉数据的细节特征;而如果数据集较小或变量分布相对简单,则较少的箱可能就足够了

该参数与 stop_limit 参数、count_distr_limit参数结合控制分箱数量,以共同控制分箱的过程和结果

参数10:positive

用于指定目标变量是好类别的标签,通过该参数的设置,用来检测 dt 中的 y 列取值是否规范,如果不规范,将会被check函数检测出来,抛出异常终止建模。

该入参默认值是 "bad|1"

在信用评分卡建模中,这通常指的是那些我们希望模型能够识别并预测出的正面事件,比如客户会偿还贷款(即“好”客户)的情况

positive 参数的设置

positive 参数应该设置为目标变量中代表正面事件的唯一值或值的列表。这个参数对于函数来说很重要,因为它决定了如何计算诸如好坏比率(Good/Bad Ratio)、信息值(IV)等关键指标,这些指标在信用评分卡的开发中至关重要。

  • 如果目标变量是二元的(比如,只有“好”和“坏”两种可能),positive 参数就应该设置为表示“好”类别的那个值。
  • 如果目标变量有多个类别,但其中只有一个被视为正面事件,那么positive 参数同样应该设置为那个代表正面事件的值。
  • 在某些情况下,如果目标变量使用了不同的编码方式(比如,用1表示“好”,用0表示“坏”),那么positive 参数就应该设置为对应的编码值。

参数11:no_cores

并发的CPU核数。默认值是None,如果该参数传的是None,会看 x 特征变量的数量,如果小于10个特征,则使用 1 核 CPU,如果大于等于 10 个特征,则使用全部的 CPU。

参数12:print_step

该参数控制函数在执行分箱(binning)过程中的信息打印级别

默认值为 0 或者 False

参数取值详解

  • 当 print_step = 0 或 False 时‌:

    • 函数将不会打印任何分箱过程中的步骤信息。
    • 这适用于不希望看到详细执行过程,只关心最终结果的用户。
  • 当 print_step > 0 或 True 时‌:

    • 函数将打印分箱过程中的一些关键步骤信息,如每个变量的分箱结果、每个分箱的坏账率(Bad Rate)、权重(Weight of Evidence, WoE)等。
    • 打印的信息量可能随着 print_step 值的增加而增加,但具体行为取决于函数的实现。
    • 这对于调试、理解分箱过程或查看中间结果非常有用。

使用建议

  • 在初次使用 woebin 函数或对新数据进行分箱时,可以将 print_step 设置为一个大于 0 的值或 True,以便查看分箱过程中的详细信息,确保分箱结果符合预期。
  • 如果已经熟悉分箱过程,并且只关心最终结果,可以将 print_step 设置为 0 或 False,以减少不必要的输出信息。
  • 该参数的使用根据个人实际情况即可。

参数13:method

用于指定分箱的方法,默认值为 tree

支持的分箱方法

1、tree(决策树分箱)‌:
  • 决策树分箱是一种基于决策树算法的分箱方法。它通过递归地划分数据集来生成最优的分箱结果。
  • 决策树分箱的优点是能够处理连续型变量和类别型变量,并且通常能够生成较为均衡的分箱结果。
  • 缺点是计算复杂度较高,可能需要较长的计算时间,尤其是在处理大数据集时。
def woebin2_tree(dtm, init_count_distr=0.02, count_distr_limit=0.05,stop_limit=0.1, bin_num_limit=8, breaks=None, spl_val=None):# initial binningbin_list = woebin2_init_bin(dtm, init_count_distr=init_count_distr, breaks=breaks, spl_val=spl_val)initial_binning = bin_list['initial_binning']binning_sv = bin_list['binning_sv']if len(initial_binning.index) == 1:return {'binning_sv': binning_sv, 'binning': initial_binning}# initialize parameterslen_brks = len(initial_binning.index)bestbreaks = NoneIVt1 = IVt2 = 1e-10IVchg = 1  ## IV gain ratiostep_num = 1# best breaks from three to n+1 binsbinning_tree = Nonewhile (IVchg >= stop_limit) and (step_num + 1 <= min([bin_num_limit, len_brks])):binning_tree = woebin2_tree_add_1brkp(dtm, initial_binning, count_distr_limit, bestbreaks)# best breaksbestbreaks = binning_tree.loc[lambda x: x['bstbrkp'] != float('-inf'), 'bstbrkp'].tolist()# information valueIVt2 = binning_tree['total_iv'].tolist()[0]IVchg = IVt2 / IVt1 - 1  ## ratio gainIVt1 = IVt2# step_numstep_num = step_num + 1if binning_tree is None: binning_tree = initial_binning# return return {'binning_sv': binning_sv, 'binning': binning_tree}
‌2、chimerge(卡方分箱)‌:
  • 卡方分箱是一种基于卡方统计量的分箱方法。它通过合并相邻的区间来减少区间数量,直到满足某个停止条件为止。
  • 卡方分箱的优点是能够处理连续型变量,并且生成的分箱结果通常具有较好的单调性。
  • 缺点是可能无法处理类别型变量,并且需要指定分箱的数量或停止条件。

卡方算法参考文献:

ChiMerge算法详解:数据离散化与应用-CSDN博客

ChiMerge:Discretization of numeric attributs

def woebin2_chimerge(dtm, init_count_distr=0.02, count_distr_limit=0.05, stop_limit=0.1, bin_num_limit=8, breaks=None, spl_val=None):# chisq = function(a11, a12, a21, a22) {#   A = list(a1 = c(a11, a12), a2 = c(a21, a22))#   Adf = do.call(rbind, A)##   Edf =#     matrix(rowSums(Adf), ncol = 1) %*%#     matrix(colSums(Adf), nrow = 1) /#     sum(Adf)##   sum((Adf-Edf)^2/Edf)# }# function to create a chisq column in initial_binningdef add_chisq(initial_binning):chisq_df = pd.melt(initial_binning, id_vars=["brkp", "variable", "bin"], value_vars=["good", "bad"],var_name='goodbad', value_name='a')\.sort_values(by=['goodbad', 'brkp']).reset_index(drop=True)###chisq_df['a_lag'] = chisq_df.groupby('goodbad')['a'].apply(lambda x: x.shift(1))#.reset_index(drop=True)chisq_df['a_rowsum'] = chisq_df.groupby('brkp')['a'].transform(lambda x: sum(x))#.reset_index(drop=True)chisq_df['a_lag_rowsum'] = chisq_df.groupby('brkp')['a_lag'].transform(lambda x: sum(x))#.reset_index(drop=True)###chisq_df = pd.merge(chisq_df.assign(a_colsum = lambda df: df.a+df.a_lag), chisq_df.groupby('brkp').apply(lambda df: sum(df.a+df.a_lag)).reset_index(name='a_sum'))\.assign(e = lambda df: df.a_rowsum*df.a_colsum/df.a_sum,e_lag = lambda df: df.a_lag_rowsum*df.a_colsum/df.a_sum).assign(ae = lambda df: (df.a-df.e)**2/df.e + (df.a_lag-df.e_lag)**2/df.e_lag).groupby('brkp').apply(lambda x: sum(x.ae)).reset_index(name='chisq')# returnreturn pd.merge(initial_binning.assign(count = lambda x: x['good']+x['bad']), chisq_df, how='left')# initial binningbin_list = woebin2_init_bin(dtm, init_count_distr=init_count_distr, breaks=breaks, spl_val=spl_val)initial_binning = bin_list['initial_binning']binning_sv = bin_list['binning_sv']# return initial binning if its row number equals 1if len(initial_binning.index)==1: return {'binning_sv':binning_sv, 'binning':initial_binning}# dtm_rowsdtm_rows = len(dtm.index)    # chisq limitfrom scipy.special import chdtrichisq_limit = chdtri(1, stop_limit)# binning with chisq columnbinning_chisq = add_chisq(initial_binning)# parambin_chisq_min = binning_chisq.chisq.min()bin_count_distr_min = min(binning_chisq['count']/dtm_rows)bin_nrow = len(binning_chisq.index)# remove brkp if chisq < chisq_limitwhile bin_chisq_min < chisq_limit or bin_count_distr_min < count_distr_limit or bin_nrow > bin_num_limit:# brkp needs to be removedif bin_chisq_min < chisq_limit:rm_brkp = binning_chisq.assign(merge_tolead = False).sort_values(by=['chisq', 'count']).iloc[0,]elif bin_count_distr_min < count_distr_limit:rm_brkp = binning_chisq.assign(count_distr = lambda x: x['count']/sum(x['count']),chisq_lead = lambda x: x['chisq'].shift(-1).fillna(float('inf'))).assign(merge_tolead = lambda x: x['chisq'] > x['chisq_lead'])# replace merge_tolead as Truerm_brkp.loc[np.isnan(rm_brkp['chisq']), 'merge_tolead']=True# order select 1strm_brkp = rm_brkp.sort_values(by=['count_distr']).iloc[0,]elif bin_nrow > bin_num_limit:rm_brkp = binning_chisq.assign(merge_tolead = False).sort_values(by=['chisq', 'count']).iloc[0,]else:break# set brkp to lead's or lag'sshift_period = -1 if rm_brkp['merge_tolead'] else 1binning_chisq = binning_chisq.assign(brkp2  = lambda x: x['brkp'].shift(shift_period))\.assign(brkp = lambda x:np.where(x['brkp'] == rm_brkp['brkp'], x['brkp2'], x['brkp']))# groupby brkpbinning_chisq = binning_chisq.groupby('brkp').agg({'variable':lambda x:np.unique(x),'bin': lambda x: '%,%'.join(x),'good': sum,'bad': sum}).assign(badprob = lambda x: x['bad']/(x['good']+x['bad']))\.reset_index()# update## add chisq to new binning dataframebinning_chisq = add_chisq(binning_chisq)## parambin_nrow = len(binning_chisq.index)if bin_nrow == 1:breakbin_chisq_min = binning_chisq.chisq.min()bin_count_distr_min = min(binning_chisq['count']/dtm_rows)# format init_bin # remove (.+\\)%,%\\[.+,)if is_numeric_dtype(dtm['value']):binning_chisq = binning_chisq\.assign(bin = lambda x: [re.sub(r'(?<=,).+%,%.+,', '', i) if ('%,%' in i) else i for i in x['bin']])\.assign(brkp = lambda x: [float(re.match('^\[(.*),.+', i).group(1)) for i in x['bin']])# return return {'binning_sv':binning_sv, 'binning':binning_chisq}

使用建议

在选择分箱方法时,应根据数据的类型(连续型或类别型)、数据的特点(如分布情况、缺失值情况等)以及具体的业务需求来进行选择

  • 如果数据中包含较多的连续型变量,并且希望分箱结果具有较好的单调性,可以考虑使用卡方分箱(chimerge)。
  • 如果数据中包含较多的类别型变量,或者希望分箱过程能够自动处理不同类型的数据,可以考虑使用决策树分箱(tree

参数14:ignore_const_cols

用于控制是否忽略常量列的分箱处理,参数类型为 bool

默认值:True,即忽略常量列的分箱处理

常量列指在整个数据集中所有行的值都相同的列,这些列对于建模通常没有提供有用的信息,因此可以忽略,从而减少不必要的计算,提高分箱的效率。

参数15:ignore_datetime_cols

用于控制是否忽略日期时间列的分箱处理,参数类型为 bool

默认值:True,即忽略日期时间列的分箱处理

日期时间列通常包含时间戳、日期或时间信息,这些信息对于某些类型的分析可能是有用的,但在分箱过程中可能需要特殊的处理。

当需要对日期时间列进行分箱处理,即ignore_datetime_cols = False 时‌,这可能需要对日期时间列进行额外的预处理,例如将它们转换为数值型特征或提取特定的日期时间组件(如年、月、日等)。

参数16:check_cate_num

用于控制在对类别型变量(categorical variables)进行分箱时,是否检查并限制每个类别中的样本数量,并在必要时进行合并或处理,参数类型为 bool

默认值:True

如果类别型变量的类别数量超过50,即会给出提示,由用户判断是否继续分箱。如果样本中有很多类别型变量,并且每个变量枚举值都非常多,那么也会非常影响建模效率。

def check_cateCols_uniqueValues(dat, var_skip = None):# character columns with too many unique valueschar_cols = [i for i in list(dat) if not is_numeric_dtype(dat[i])]if var_skip is not None: char_cols = list(set(char_cols) - set(str_to_list(var_skip)))char_cols_too_many_unique = [i for i in char_cols if len(dat[i].unique()) >= 50]if len(char_cols_too_many_unique) > 0:print('>>> There are {} variables have too many unique non-numberic values, which might cause the binning process slow. Please double check the following variables: \n{}'.format(len(char_cols_too_many_unique), ', '.join(char_cols_too_many_unique)))print('>>> Continue the binning process?')print('1: yes \n2: no')cont = int(input("Selection: "))while cont not in [1, 2]:cont = int(input("Selection: "))if cont == 2:raise SystemExit(0)return None

参数17:replace_blank

用于控制如何处理数据中的空白(或缺失)值,参数类型为 bool

默认值:True

def rep_blank_na(dat): # cant replace blank string in categorical value with nan# 如果有重复的索引,则重置索引if dat.index.duplicated().any():dat = dat.reset_index(drop = True)warnings.warn('There are duplicated index in dataset. The index has been reseted.')blank_cols = [i for i in list(dat) if dat[i].astype(str).str.findall(r'^\s*$').apply(lambda x:0 if len(x)==0 else 1).sum()>0]if len(blank_cols) > 0:warnings.warn('There are blank strings in {} columns, which are replaced with NaN. \n (ColumnNames: {})'.format(len(blank_cols), ', '.join(blank_cols)))
#        dat[dat == [' ','']] = np.nan
#        dat2 = dat.apply(lambda x: x.str.strip()).replace(r'^\s*$', np.nan, regex=True)dat.replace(r'^\s*$', np.nan, regex=True)return dat

参数18:save_breaks_list

用于控制是否将分箱后的断点(或称为区间边界)保存为一个列表。这个参数对于后续的分箱处理、模型训练或结果分析可能非常重要,因为它决定了分箱的具体方式和每个箱子的边界

默认值:None

如果该参数不为 None,传入的是 String 类型数据,则会用于文件名,将分箱信息保存在文件中。具体由 bins_to_breaks 函数实现

def bins_to_breaks(bins, dt, to_string=False, save_string=None):if isinstance(bins, dict):bins = pd.concat(bins, ignore_index=True)# x variablesxs_all = bins['variable'].unique()# dtypes of  variablesvars_class = pd.DataFrame({'variable': xs_all,'not_numeric': [not is_numeric_dtype(dt[i]) for i in xs_all]})# breakslist of binsbins_breakslist = bins[~bins['breaks'].isin(["-inf","inf","missing"]) & ~bins['is_special_values']]bins_breakslist = pd.merge(bins_breakslist[['variable', 'breaks']], vars_class, how='left', on='variable')bins_breakslist.loc[bins_breakslist['not_numeric'], 'breaks'] = '\''+bins_breakslist.loc[bins_breakslist['not_numeric'], 'breaks']+'\''bins_breakslist = bins_breakslist.groupby('variable')['breaks'].agg(lambda x: ','.join(x))if to_string:bins_breakslist = "breaks_list={\n"+', \n'.join('\''+bins_breakslist.index[i]+'\': ['+bins_breakslist[i]+']' for i in np.arange(len(bins_breakslist)))+"}"if save_string is not None:brk_lst_name = '{}_{}.py'.format(save_string, time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time())))with open(brk_lst_name, 'w') as f:f.write(bins_breakslist)print('[INFO] The breaks_list is saved as {}'.format(brk_lst_name))return return bins_breakslist

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/84159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

英语写作中“假设”suppose, assume, presume 的用法

一、suppose 是给出推理的前提&#xff0c;与事实无关&#xff0c;例如&#xff1a; Suppose x >0. Then the square root of x is a real number. &#xff08;假设x大于0&#xff0c;则x的平方根是实数。&#xff09; Suppose Jack and Alice share a private channel. …

CAD标注样式如何设置?详细教程来了

CAD中有很多的标注&#xff0c;比如线性标注&#xff0c;对齐标注&#xff0c;坐标标注&#xff0c;面积标注&#xff0c;直径标注&#xff0c;弧长标注等等&#xff0c;标注的种类多&#xff0c;标注的样式也多&#xff0c;今天来给大家介绍一下浩辰CAD看图王中如何设置不同的…

vscode include总是报错

VSCode 的 C/C 扩展可以通过配置 c_cpp_properties.json 来使用 compile_commands.json 文件中的编译信息&#xff0c;包括 include path、编译选项等。这样可以确保 VSCode 的 IntelliSense 与实际编译环境保持一致。 方法一&#xff1a;直接指定 compile_commands.json 路径…

自动化立体仓库WCS与PLC通讯设计规范

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。欢迎大家使用我们的仓储物流技术AI智能体。 新书《智能物流系统构成与技术实践》 新书《智能仓储项目出海-英语手册&#xff0c;必备&#xff01;》 完整版文件和更多学习资料&#xf…

【window QT开发】简易的对称密钥加解密工具(包含图形应用工具和命令行工具)

前言 项目开发时&#xff0c;配置文件中某些信息不适合直接明文显示&#xff0c;本文提供基于对称密钥的AES-256算法的加解密工具&#xff0c;可集成到项目中。 AES讲解 以下是我分享的一个在国产信创系统(Linux)下使用openssl实现AES加解密的博文 对称加密--AES加解密 本文…

「极简」扣子(coze)教程 | 小程序UI设计进阶(二)!让系统动起来,“禁用”,“加载”状态设置

大家好&#xff0c;上一期大师兄通过一个例子来介绍一下扣子界面中“可见性”的应用。今天大师兄想再进一步介绍控件中的其他一些重要的属性。 扣子&#xff08;coze&#xff09;编程 「极简」扣子(coze)教程 | 小程序UI设计进阶&#xff01;控件可见性设置 「极简」扣子(coze…

前端三件套之html详解

目录 一 认识 二 标签的分类 三 标签 body标签 标题标签 段落标签 换行标签 水平分割线 文本格式化标签 图片标签 音频标签 链接标签 列表标签 表格标签 表单标签 input标签 下拉菜单标签 textarea文本域标签 label标签 语义化标签 button标签 字符实体 …

Google Play 账号创建及材料准备

1&#xff1a;注册一个关联Google Play账号的Google账号&#xff0c;关联邮箱进行自动转发 2&#xff1a;准备一张Visa、Master、JCB、运通卡或Discover等美国信用卡或全球付虚拟信用卡&#xff0c;用来支付25美金的GP账号注册费 3&#xff1a;为避免出现关联原因被封&#x…

Pycharm和Flask的学习心得(4和5)

一&#xff1a;认识路由&#xff1a; &#xff08;1&#xff09;&#xff1a;接受请求的类型&#xff1a; app.route(hello ,methods [GET ,POST]) 请求类型主要有两种(常用)&#xff1a;GET 和 POST ; GET: 直接输入的网址&#xff08;url访问的就是GET请求&#xff09; …

DeepSeek 赋能智能电网:从技术革新到全场景应用实践

目录 一、智能电网的发展现状与挑战二、DeepSeek 技术解析2.1 DeepSeek 技术原理2.2 DeepSeek 技术优势 三、DeepSeek 在智能电网中的具体应用3.1 设备管理智能化3.2 电网运行优化3.3 客户服务提升3.4 规划建设智能化3.5 经营管理高效化3.6 办公辅助便捷化 四、DeepSeek 在智能…

MFC 编程中 OnInitDialog 函数

核心作用 对话框初始化入口 &#xff1a;创建完成后第一个执行的函数。是对话框的起点。控件操作安全期 &#xff1a;此时所有控件已创建完成。可以安全地进行控件的初始化、属性设置等操作。界面布局最佳时机 &#xff1a;窗口显示前完成初始化设置。可以进行布局调整、数据初…

前端地图数据格式标准及应用

前端地图数据格式标准及应用 坐标系EPSGgeojson标准格式基于OGC标准的地图服务shapefile文件3D模型数据常见地图框架 坐标系EPSG EPSG&#xff08;European Petroleum Survey Group&#xff09;是一个国际组织&#xff0c;负责维护和管理地理坐标系统和投影系统的标准化编码 E…

Python爬虫(35)Python爬虫高阶:基于Docker集群的动态页面自动化采集系统实战

目录 一、技术演进与行业痛点二、核心技术栈深度解析2.1 动态渲染三件套2.2 Docker集群架构设计2.3 自动化调度系统 三、进阶实战案例3.1 电商价格监控系统1. 技术指标对比2. 实现细节 3.2 新闻聚合平台1. WebSocket监控2. 字体反爬破解 四、性能优化与运维方案4.1 资源消耗对比…

04-jenkins学习之旅-java后端项目部署实践

1、创建被管理项目 2、构建流程说明 jenkins其实就是将服务部署拆分成了&#xff1a; 1、拉取代码(git) 2、打包编译 3、自定义脚本(jar复制、执行启动脚本) 4、部署成功后的一些通知等 3、demo配置 3.1、General 3.2 源码管理 添加用户名密码方式如下图 3.2.1 常见错误(r…

科研经验贴:AI领域的研究方向总结

一、数据集&#xff08;Dataset&#xff09; 定义&#xff1a; 用于训练、验证和测试模型的样本集合&#xff0c;通常包含输入特征&#xff08;如图像、文本&#xff09;和对应标签&#xff08;如类别、回归值&#xff09;。 关键作用&#xff1a; 数据划分&#xff1a; 训练…

Android 网络全栈攻略(四)—— 从 OkHttp 拦截器来看 HTTP 协议一

上一篇我们详解了 OkHttp 的众多配置&#xff0c;本篇来看 OkHttp 是如何通过责任链上的内置拦截器完成 HTTP 请求与响应的&#xff0c;目的是更好地深入理解 HTTP 协议。这仍然是一篇偏向于协议实现向的文章&#xff0c;重点在于 HTTP 协议的实现方法与细节&#xff0c;关于责…

免费AI工具整理

1、NVIDIA models ALL&#xff1a;Try NVIDIA NIM APIs example&#xff1a;llama-3.1-405b-instruct Model by Meta | NVIDIA NIM 2、文心一言 文心一言 3、纳米AI 纳米AI搜索 4、其他 ChatGPT 镜像网址&#xff08;5月持续更新&#xff09; - 最优网址

C++ std::find() 函数全解析

std::find()是C标准库中用于线性查找的基础算法&#xff0c;属于<algorithm>头文件&#xff0c;可应用于任何支持迭代器的容器。 一、函数原型与参数 template< class InputIt, class T > InputIt find( InputIt first, InputIt last, const T& value );​​…

MySQL--day6--单行函数

&#xff08;以下内容全部来自上述课程&#xff09; 单行函数 1. 内置函数及分类 单行函数聚合函数&#xff08;或分组函数&#xff09; 1.1 单行函数特点 操作数据对象接受参数返回一个结果只对一行进行变换每行返回一个结果可以嵌套参数可以是一列或一个值 2. 数值函…

GO语言学习(九)

GO语言学习&#xff08;九&#xff09; 上一期我们了解了实现web的工作中极为重要的net/http抱的细节讲解&#xff0c;大家学会了实现web开发的一些底层基础知识&#xff0c;在这一期我来为大家讲解一下web工作的一个重要方法&#xff0c;&#xff1a;使用数据库&#xff0c;现…