I'm using the OptBinning package to bin some numeric data. I'm following this example to do this. And from this tutorial I read that "... the best way to view BinningProcess
is as a wrapper for OptimalBinning
", which implies that they should both give the same outputs. However, I'm seeing they give different outputs for some features and the same for others. Why is this the case? Below is an example showing how the two methods lead to the same output for 'mean radius' but not 'worst radius' using the breast cancer data in sklearn.
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from optbinning import BinningProcess
from optbinning import OptimalBinning
# Load data
data = load_breast_cancer()
df = pd.DataFrame(data.data, columns=data.feature_names)
# Bin 'mean radius' data using OptimalBinning method
var = 'mean radius'
x = df[var]
y = data.target
optb = OptimalBinning(name=var, dtype="numerical")
optb.fit(x, y)
binning_table = optb.binning_table
binning_table.build()['WoE']
0 -3.12517
1 -2.71097
2 -1.64381
3 -0.839827
4 -0.153979
5 2.00275
6 5.28332
7 0
8 0
Totals
Name: WoE, dtype: object
# Bin 'mean radius' using BinningProcess method
var = ['mean radius']
bc_pipe = Pipeline([('WOE Binning', BinningProcess(variable_names=var))])
preprocessor = ColumnTransformer([('Numeric Pipeline', bc_pipe, var)], remainder='passthrough')
preprocessor.fit(df, y)
df_processed = preprocessor.transform(df)
df_processed = pd.DataFrame(df_processed, columns=df.columns)
df_processed[var[0]].unique()
array([ 5.28332344, -3.12517033, -1.64381421, -0.15397917, 2.00275405,
-0.83982705, -2.71097154])
## We see that the Weight of Evidence (WoE) values are the same for 'mean radius' using both methods (except for the 0's, which we can ignore for now)
# Bin 'worst radius' using OptimalBinning process
var = 'worst radius'
x = df[var]
y = data.target
optb = OptimalBinning(name=var, dtype="numerical")
optb.fit(x, y)
binning_table = optb.binning_table
binning_table.build()['WoE']
0 -4.56645
1 -2.6569
2 -0.800606
3 -0.060772
4 1.61976
5 5.5251
6 0
7 0
Totals
Name: WoE, dtype: object
# Bin 'worst radius' using BinningProcess method
var = ['worst radius']
bc_pipe = Pipeline([('WOE Binning', BinningProcess(variable_names=var))])
preprocessor = ColumnTransformer([('Numeric Pipeline', bc_pipe, var)], remainder='passthrough')
preprocessor.fit(df, y)
df_processed = preprocessor.transform(df)
df_processed = pd.DataFrame(df_processed, columns=df.columns)
df_processed[var[0]].unique()
array([0.006193 , 0.003532 , 0.004571 , 0.009208 , 0.005115 , 0.005082 ,
0.002179 , 0.005412 , 0.003749 , 0.01008 , 0.003042 , 0.004144 ,
0.01284 , 0.003002 , 0.008093 , 0.005466 , 0.002085 , 0.004142 ,
0.001997 , 0.0023 , 0.002425 , 0.002968 , 0.004394 , 0.001987 ,
0.002801 , 0.007444 , 0.003711 , 0.004217 , 0.002967 , 0.003742 ,
0.00456 , 0.005667 , 0.003854 , 0.003896 , 0.003817 , ... ])
## We now see that for 'worst radius' the two WoE's are not the same. Why?