Skip to main content

OptBinning (slim fork)

CI Python License Tests Coverage

Attribution

This is a maintenance fork of OptBinning, created and authored by Guillermo Navas-Palencia (g.navas.palencia@gmail.com).

The mathematical formulation, the algorithms and essentially all of the code in this repository are their work, published under the Apache License 2.0 and reproduced here under its terms. The per-module copyright headers are theirs and are kept intact. This fork was branched at upstream 0.21.0 and contributes no new algorithms — it exists only to keep that work running on current Python and a current dependency stack. If OptBinning is useful to you, the credit and the citations belong upstream.

Upstream documentation (this fork does not carry its own copy): http://gnpalencia.org/optbinning/ · Upstream repository: https://github.com/guillermo-navas-palencia/optbinning

OptBinning is a Python library implementing a rigorous and flexible mathematical programming formulation to solve the optimal binning problem for a binary, continuous and multiclass target, incorporating constraints not previously addressed.


About this fork

Despite the name, optbinning-slim is not a reduced version of the library. "Slim" refers to the dependency and packaging surface, not the feature set.

What this fork changes

Python Requires >= 3.13. CI runs 3.13 and 3.14 on Linux, Windows and macOS. Upstream's matrix stops at 3.12.
Dependencies Version floors raised to a current, coherent stack (see Dependencies). The ortools>=9.4,<9.12 upper cap was dropped — the fork tracks current OR-Tools.
Compatibility fixes Fixes for behaviour changes in pandas 3.0 (string dtype detection in BinningProcess), NumPy 2.x and scikit-learn 1.7+.
Piecewise solvers "clarabel" is accepted as a solver for the piecewise estimators, alongside "ecos", "osqp", "direct", "scs" and "auto". As of ropwr 1.2, "auto" resolves to "clarabel"; before that it resolved to "ecos".
Packaging Metadata moved from setup.py to a PEP 621 pyproject.toml, which is now the only place dependencies are declared — requirements.txt and test_requirements.txt are gone, replaced by environment.yml for conda users. matplotlib is a hard requirement rather than an implicit one; ecos moved into the test extra, because test_binning_piecewise.py::test_solvers needs it. The distribution is named optbinning-slim on PyPI while the import package stays optbinning.
LocalSolver solver="ls" and the LocalSolver integration were removed. localsolver is not on PyPI and the hexaly package that succeeds it provides no localsolver module, so the option was unusable for anyone installing this package. OptimalBinning accepts ("cp", "mip"), as every other estimator already did.
Documentation Upstream's Sphinx sources (doc/) are not carried in this fork — they describe the library to its users and are maintained upstream. Read them at http://gnpalencia.org/optbinning/, or in the upstream repository. Docstrings in this repository remain the source of truth for behaviour and are kept current.

Release notes are in CHANGELOG.md. Divergences from upstream, and the reasoning behind each, are recorded in reports/DECISIONS.md so that a future merge with upstream stays tractable.

What this fork does not change

No subsystem has been removed. Every one upstream ships is still here and still tested: distributed / sketch binning, uncertainty (scenario-based binning), counterfactual explanations, multidimensional (2D) binning, piecewise binning, and all plotting methods. Everything exported from optbinning/__init__.py is public API and is expected to keep working:

BinningProcess          BinningProcessSketch      ContinuousOptimalBinning
ContinuousOptimalBinning2D                        ContinuousOptimalPWBinning
MDLP                    MulticlassOptimalBinning  OptimalBinning
OptimalBinning2D        OptimalBinningSketch      OptimalPWBinning
SBOptimalBinning        Scorecard

The one option that did go is solver="ls", whose dependency cannot be installed at all — see the table above. No new algorithms are added either. Behaviour is intended to match upstream except where a fix was required, and every such case is documented in CHANGELOG.md.


Installation

On PyPI the distribution is named optbinning-slim; the import name stays optbinning, so the fork is a drop-in replacement for upstream. For that same reason optbinning and optbinning-slim must not be installed into the same environment — they claim the same import package.

The package is prepared for release but has not been uploaded yet (as of 2026-08-23). Until it is, install from source:

git clone https://github.com/dennisdeh/optbinning-slim.git
cd optbinning-slim
pip install -e .

For the upstream release, use pip install optbinning instead.

With conda

environment.yml builds the optbinning development environment — the interpreter from conda-forge, every project dependency resolved from pyproject.toml:

conda env create -f environment.yml
conda activate optbinning

Optional extras

pip install -e ".[distributed]"        # batch and stream binning (sketch algorithms)
pip install -e ".[ecos]"               # the ECOS solver, used by piecewise binning
pip install -e ".[test]"               # test suite, linting and coverage
pip install -e ".[dev]"                # all of the above, plus build and twine

Dependencies

Requires Python >= 3.13. Dependencies are declared only in pyproject.toml — there is no requirements.txt to keep in sync.

Package This fork Upstream 0.21.0
matplotlib >=3.10 (unpinned)
numpy >=2.3 >=1.16.1
ortools >=9.14 >=9.4,<9.12
pandas >=2.3 (unpinned)
ropwr >=1.2 >=1.0.0
scikit-learn >=1.7 >=1.6.0
scipy >=1.15 >=1.6.0

Extras: distributed → pympler, tdigest. ecos → ecos. test → coverage, ecos, flake8, pyarrow, pympler, pytest, tdigest. dev → all extras plus build, twine.

Building a release

python -m build                   # sdist + wheel into dist/
python -m twine check --strict dist/*
python -m twine upload dist/*     # requires a PyPI token

Testing

Run the suite from the repository root — several tests write to relative paths under tests/results/.

pytest                                                       # full suite
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics

Current status — measured 2026-08-23 on Python 3.13.15:

Result 212 passed, 0 failed (9 warnings)
Test modules 20
Wall clock 188 s (binning problems are real solver runs; the suite is not instant)
Statement coverage 89% — 11,301 statements, 1,244 uncovered
Lint gate flake8 --select=E9,F63,F7,F82 → 0 issues

Verified against: numpy 2.5.2, pandas 3.0.5, scipy 1.18.1, scikit-learn 1.9.0, ortools 9.15.6755, matplotlib 3.11.1, ropwr 1.2.0, ecos 2.0.14.

Coverage by subsystem:

Area Coverage
scorecard/ (scorecard, monitoring, plots, counterfactual) 94%
binning/multidimensional/ (2D binning) 92%
binning/piecewise/ 92%
binning/distributed/ (sketch algorithms) 86%
binning/uncertainty/ (scenario binning) 96%
Core estimators (binning.py, continuous_binning.py, binning_process.py) 82–93%
Overall 89%

The lowest-covered modules are binning/piecewise/binning_information.py (69%), binning/multidimensional/mip_2d.py (73%) and binning/distributed/bsketch.py (75%) — reporting paths and solver-specific branches that the default configuration does not exercise. binning/mdlp.py and binning/distributed/plots.py, both largely untested upstream, are now at 100%.

The suite is fully offline — no network access and no credentials are required. Fixtures live in tests/data/ (breast_cancer.csv, boston_housing.csv, breast_cancer.parquet). The distributed extra (tdigest, pympler) and ecos gate whole test modules: without them those modules fail to import rather than skipping, so install the extras before reporting a failure.

Open defects and planned improvements are tracked in reports/OPEN_ITEMS.md and reports/IMPROVEMENT_SUGGESTIONS.md.


Getting started

The library follows the scikit-learn contract — fit / transform / fit_transform — plus the optbinning-specific binning_table, splits, status and information().

Upstream's documentation and tutorials apply unchanged to this fork:

Papers

binning binary binning data stream
binning 2d binning 2d woe

Example: optimal binning with a binary target

Load a well-known dataset and choose a variable to discretize plus the binary target.

import pandas as pd
from sklearn.datasets import load_breast_cancer

data = load_breast_cancer()
df = pd.DataFrame(data.data, columns=data.feature_names)

variable = "mean radius"
x = df[variable].values
y = data.target

Instantiate an OptimalBinning object. We pass the variable name, its data type, and a solver — here the constraint programming solver. Fit it with arrays x and y.

from optbinning import OptimalBinning

optb = OptimalBinning(name=variable, dtype="numerical", solver="cp")
optb.fit(x, y)

Check status and retrieve the optimal split points:

>>> optb.status
'OPTIMAL'

>>> optb.splits
array([11.42500019, 12.32999992, 13.09499979, 13.70499992, 15.04500008,
       16.92500019])

The optimal binning algorithms return a binning table, which displays the binned data and several metrics for each bin. Call build(), which returns a pandas.DataFrame:

>>> optb.binning_table.build()
                   Bin  Count  Count (%)  Non-event  Event  Event rate       WoE        IV        JS
0        (-inf, 11.43)    118   0.207381          3    115    0.974576 -3.125170  0.962483  0.087205
1       [11.43, 12.33)     79   0.138840          3     76    0.962025 -2.710972  0.538763  0.052198
2       [12.33, 13.09)     68   0.119508          7     61    0.897059 -1.643814  0.226599  0.025513
3       [13.09, 13.70)     49   0.086116         10     39    0.795918 -0.839827  0.052131  0.006331
4       [13.70, 15.05)     83   0.145870         28     55    0.662651 -0.153979  0.003385  0.000423
5       [15.05, 16.93)     54   0.094903         44     10    0.185185  2.002754  0.359566  0.038678
6         [16.93, inf)    118   0.207381        117      1    0.008475  5.283323  2.900997  0.183436
7              Special      0   0.000000          0      0    0.000000  0.000000  0.000000  0.000000
8              Missing      0   0.000000          0      0    0.000000  0.000000  0.000000  0.000000
Totals                    569   1.000000        212    357    0.627417            5.043925  0.393784

(Output reproduced on this fork, 2026-08-23, with the dependency stack listed under Testing.)

Use plot to visualize the histogram and the WoE or event rate curve. The Bin ID corresponds to the binning table index.

>>> optb.binning_table.plot(metric="woe")

binning woe

Optionally, show the binning plot with the actual bin widths:

>>> optb.binning_table.plot(metric="woe", style="actual", add_special=False, add_missing=False)

binning split woe

Now transform the original data into WoE or event rate values. Note that transform returns a metric, not bin indices:

x_transform_woe = optb.transform(x, metric="woe")
x_transform_event_rate = optb.transform(x, metric="event_rate")

The analysis method performs a statistical analysis of the binning table, computing the Gini index, Information Value (IV), Jensen-Shannon divergence and the quality score. Several statistical significance tests between consecutive bins are also performed.

>>> optb.binning_table.analysis()
---------------------------------------------
OptimalBinning: Binary Binning Table Analysis
---------------------------------------------

  General metrics

    Gini index               0.87541620
    IV (Jeffrey)             5.04392547
    JS (Jensen-Shannon)      0.39378376
    Hellinger                0.47248971
    Triangular               1.25592041
    KS                       0.72862164
    HHI                      0.15727342
    HHI (normalized)         0.05193260
    Cramer's V               0.80066760
    Quality score            0.00000000

  Monotonic trend            descending

  Significance tests

    Bin A  Bin B  t-statistic       p-value  P[A > B]      P[B > A]
        0      1     0.252432  6.153679e-01  0.684380  3.156202e-01
        1      2     2.432829  1.188183e-01  0.948125  5.187465e-02
        2      3     2.345804  1.256207e-01  0.937874  6.212635e-02
        3      4     2.669235  1.023052e-01  0.955269  4.473083e-02
        4      5    29.910964  4.523477e-08  1.000000  9.814594e-12
        5      6    19.324617  1.102754e-05  0.999999  1.216668e-06

Print an overview of the option settings, problem statistics and the solution:

>>> optb.information(print_level=2)
optbinning (Version 0.22.0)
Copyright (c) 2019-2025 Guillermo Navas-Palencia, Apache License 2.0

  Begin options
    name                         mean radius   * U
    dtype                          numerical   * d
    prebinning_method                   cart   * d
    solver                                cp   * d
    divergence                            iv   * d
    max_n_prebins                         20   * d
    min_prebin_size                     0.05   * d
    min_n_bins                            no   * d
    max_n_bins                            no   * d
    min_bin_size                          no   * d
    max_bin_size                          no   * d
    min_bin_n_nonevent                    no   * d
    max_bin_n_nonevent                    no   * d
    min_bin_n_event                       no   * d
    max_bin_n_event                       no   * d
    monotonic_trend                     auto   * d
    min_event_rate_diff                    0   * d
    max_pvalue                            no   * d
    max_pvalue_policy            consecutive   * d
    gamma                                  0   * d
    class_weight                          no   * d
    cat_cutoff                            no   * d
    user_splits                           no   * d
    user_splits_fixed                     no   * d
    special_codes                         no   * d
    split_digits                          no   * d
    mip_solver                           bop   * d
    time_limit                           100   * d
    verbose                            False   * d
  End options

  Name    : mean radius
  Status  : OPTIMAL

  Pre-binning statistics
    Number of pre-bins                     9
    Number of refinements                  1

  Solver statistics
    Type                                  cp
    Number of booleans                    26
    Number of branches                    58
    Number of conflicts                    0
    Objective value                  5043922
    Best objective bound             5043922

  Timing
    Total time                          0.04 sec
    Pre-processing                      0.00 sec   (  0.33%)
    Pre-binning                         0.00 sec   (  5.54%)
    Solver                              0.04 sec   ( 93.03%)
      model generation                  0.03 sec   ( 85.61%)
      optimizer                         0.01 sec   ( 14.39%)
    Post-processing                     0.00 sec   (  0.30%)

Note on reproducibility. OR-Tools may return a different optimal solution of equal objective across versions and platforms. When comparing results, pin on the objective value and on status, not on incidental split values.


Example: optimal binning 2D with a binary target

Choose two variables to discretize plus the binary target.

import pandas as pd
from sklearn.datasets import load_breast_cancer

data = load_breast_cancer()
df = pd.DataFrame(data.data, columns=data.feature_names)

variable1 = "mean radius"
variable2 = "worst concavity"
x = df[variable1].values
y = df[variable2].values
z = data.target

Instantiate OptimalBinning2D, passing the variable names and monotonic trends, then fit with arrays x, y and z.

from optbinning import OptimalBinning2D

optb = OptimalBinning2D(name_x=variable1, name_y=variable2,
                        monotonic_trend_x="descending",
                        monotonic_trend_y="descending", min_bin_size=0.05)
optb.fit(x, y, z)
>>> optb.binning_table.build()
                Bin x         Bin y  Count  Count (%)  Non-event  Event  Event rate       WoE        IV        JS
0        (-inf, 13.70)  (-inf, 0.21)    219   0.384886          1    218    0.995434 -4.863346  2.946834  0.199430
1         [13.70, inf)  (-inf, 0.21)     48   0.084359          5     43    0.895833 -1.630613  0.157946  0.017811
2        (-inf, 13.09)  [0.21, 0.38)     48   0.084359          1     47    0.979167 -3.328998  0.422569  0.037010
3       [13.09, 15.05)  [0.21, 0.38)     46   0.080844         17     29    0.630435 -0.012933  0.000013  0.000002
4         [15.05, inf)  [0.21, 0.32)     32   0.056239         29      3    0.093750  2.789833  0.358184  0.034271
5         [15.05, inf)   [0.32, inf)    129   0.226714        128      1    0.007752  5.373180  3.229133  0.201294
6        (-inf, 15.05)   [0.38, inf)     47   0.082601         31     16    0.340426  1.182548  0.119920  0.014173
7              Special       Special      0   0.000000          0      0    0.000000  0.000000  0.000000  0.000000
8              Missing       Missing      0   0.000000          0      0    0.000000  0.000000  0.000000  0.000000
Totals                                  569   1.000000        212    357    0.627417            7.234600  0.503991

As with 1D binning, you can generate a 2D histogram to visualize WoE and event rate:

>>> optb.binning_table.plot(metric="event_rate")

binning 2d example


Example: scorecard with a continuous target

Load the California housing dataset.

import pandas as pd

from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import HuberRegressor

from optbinning import BinningProcess
from optbinning import Scorecard

data = fetch_california_housing()

target = "target"
variable_names = data.feature_names
X = pd.DataFrame(data.data, columns=variable_names)
y = data.target

Instantiate a binning process, an estimator, and a scorecard with a scaling method and reverse mode.

binning_process = BinningProcess(variable_names)

estimator = HuberRegressor(max_iter=200)

scorecard = Scorecard(binning_process=binning_process, estimator=estimator,
                      scaling_method="min_max",
                      scaling_method_params={"min": 0, "max": 100},
                      reverse_scorecard=True)

scorecard.fit(X, y)

Print an overview of the option settings, problem statistics, and the number of selected variables after the binning process.

>>> scorecard.information(print_level=2)
optbinning (Version 0.22.0)
Copyright (c) 2019-2025 Guillermo Navas-Palencia, Apache License 2.0

  Begin options
    binning_process                      yes   * U
    estimator                            yes   * U
    scaling_method                   min_max   * U
    scaling_method_params                yes   * U
    intercept_based                    False   * d
    reverse_scorecard                   True   * U
    rounding                           False   * d
    verbose                            False   * d
  End options

  Statistics
    Number of records                  20640
    Number of variables                    8
    Target type                   continuous

    Number of numerical                    8
    Number of categorical                  0
    Number of selected                     8

  Timing
    Total time                          2.31 sec
    Binning process                     1.83 sec   ( 79.00%)
    Estimator                           0.41 sec   ( 17.52%)
    Build scorecard                     0.08 sec   (  3.40%)
      rounding                          0.00 sec   (  0.00%)

Two scorecard styles are available: style="summary" shows the variable name, its bins and the assigned points; style="detailed" adds information from the corresponding binning table.

>>> scorecard.table(style="summary")
     Variable                 Bin     Points
0      MedInc        [-inf, 1.90)   9.869224
1      MedInc        [1.90, 2.16)  10.896940
2      MedInc        [2.16, 2.37)  11.482997
3      MedInc        [2.37, 2.66)  12.607805
4      MedInc        [2.66, 2.88)  13.609078
..        ...                 ...        ...
2   Longitude  [-118.33, -118.26)  10.470401
3   Longitude  [-118.26, -118.16)   9.092391
4   Longitude      [-118.16, inf)  10.223936
5   Longitude             Special   1.376862
6   Longitude             Missing   1.376862

[94 rows x 3 columns]
>>> scorecard.table(style="detailed")
     Variable  Bin id                 Bin  Count  Count (%)  ...  Zeros count       WoE        IV  Coefficient     Points
0      MedInc       0        [-inf, 1.90)   2039   0.098789  ...            0 -0.969609  0.095786     0.990122   9.869224
1      MedInc       1        [1.90, 2.16)   1109   0.053731  ...            0 -0.836618  0.044952     0.990122  10.896940
2      MedInc       2        [2.16, 2.37)   1049   0.050824  ...            0 -0.760779  0.038666     0.990122  11.482997
3      MedInc       3        [2.37, 2.66)   1551   0.075145  ...            0 -0.615224  0.046231     0.990122  12.607805
4      MedInc       4        [2.66, 2.88)   1075   0.052083  ...            0 -0.485655  0.025295     0.990122  13.609078
..        ...     ...                 ...    ...        ...  ...          ...       ...       ...          ...        ...
2   Longitude       2  [-118.33, -118.26)   1120   0.054264  ...            0 -0.011006  0.000597     0.566265  10.470401
3   Longitude       3  [-118.26, -118.16)   1127   0.054603  ...            0 -0.322802  0.017626     0.566265   9.092391
4   Longitude       4      [-118.16, inf)   6530   0.316376  ...            0 -0.066773  0.021125     0.566265  10.223936
5   Longitude       5             Special      0   0.000000  ...            0 -2.068558  0.000000     0.566265   1.376862
6   Longitude       6             Missing      0   0.000000  ...            0 -2.068558  0.000000     0.566265   1.376862

[94 rows x 14 columns]

Compute the score and the predicted target using the fitted estimator:

score = scorecard.score(X)
y_pred = scorecard.predict(X)

fetch_california_housing downloads the dataset on first use, so this example needs network access. The test suite itself does not.


Example: counterfactual explanations for a scorecard

Changed in this fork. Upstream's version of this example called sklearn.datasets.load_boston, which was removed in scikit-learn 1.2 — the example no longer runs as written. It is shown below using the Boston housing CSV bundled with this repository (tests/data/boston_housing.csv, loaded via tests.datasets), so it is offline and reproducible from a clone. The loader lives in the test package, not in the installed wheel, so run this from the repository root.

Build a scorecard, then fit a Counterfactual on the same data used to develop it.

import pandas as pd
from sklearn.linear_model import HuberRegressor

from optbinning import BinningProcess, Scorecard
from optbinning.scorecard import Counterfactual
from tests.datasets import load_boston

data = load_boston()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target

scorecard = Scorecard(binning_process=BinningProcess(list(data.feature_names)),
                      estimator=HuberRegressor(max_iter=200),
                      scaling_method="min_max",
                      scaling_method_params={"min": 0, "max": 100},
                      reverse_scorecard=True).fit(X, y)

cf = Counterfactual(scorecard=scorecard)
cf.fit(X)

query = X.iloc[0, :].to_frame().T

The scorecard predicts 24.88 for this sample. We want to know what would have to change for it to predict at least 30.

>>> query
      CRIM    ZN  INDUS  CHAS    NOX     RM   AGE   DIS  RAD    TAX  PTRATIO      B  LSTAT
0  0.00632  18.0   2.31   0.0  0.538  6.575  65.2  4.09  1.0  296.0     15.3  396.9   4.98

>>> scorecard.predict(query)
array([24.88133986])

Generate a single counterfactual explanation:

>>> cf.generate(query=query, y=30, outcome_type="continuous", n_cf=1, max_changes=3,
...             hard_constraints=["min_outcome"])

>>> cf.status
'OPTIMAL'

>>> cf.display(show_only_changes=True, show_outcome=True)
  CRIM ZN INDUS CHAS           NOX RM AGE DIS RAD               TAX PTRATIO                 B LSTAT    outcome
0    -  -     -    -  (-inf, 0.42)  -   -   -   -  [222.50, 267.50)       -  [393.71, 395.65)     -  30.063077

(Run on this fork, 2026-08-23. Exact values depend on the fitted estimator and on the solver; see the reproducibility note above.)

You can also request several counterfactuals at once, enforcing diversity on the feature values and restricting the search to actionable features:

>>> cf.generate(query=query, y=30, outcome_type="continuous", n_cf=3, max_changes=3,
...             hard_constraints=["diversity_values", "min_outcome"],
...             actionable_features=["CRIM", "NOX", "RM", "PTRATIO"])

>>> cf.status
'OPTIMAL'

>>> cf.display(show_only_changes=True, show_outcome=True)

Benchmarks

These are upstream's published benchmarks, reproduced here for reference. They were measured by the original author on the hardware and software versions stated below and have not been re-measured on this fork's dependency stack.

The following table shows how OptBinning compares to scorecardpy 0.1.9.1.1 on a selection of variables from the public Home Credit Default Risk Kaggle dataset (307,511 samples). The experiments were run on an Intel(R) Core(TM) i5-3317 CPU at 1.70 GHz, single core, on Linux. For scorecardpy, default settings were used, only increasing bin_num_limit=20. For OptBinning, default settings were used (max_n_prebins=20), only changing max_pvalue=0.05.

Using the shifted (by 1 second) geometric mean — the measure typically used in mathematical optimization benchmarks — OptBinning is 17x faster than scorecardpy, with an average IV increment of 12%, while also supporting many more constraints and monotonicity options.

Variable scorecardpy time scorecardpy IV optbinning time optbinning IV
AMT_INCOME_TOTAL 6.18 s 0.010606 0.363 s 0.011705
NAME_CONTRACT_TYPE (C) 3.72 s 0.015039 0.148 s 0.015039
AMT_CREDIT 7.10 s 0.053593 0.634 s 0.059311
ORGANIZATION_TYPE (C) 6.31 s 0.063098 0.274 s 0.071520
AMT_ANNUITY 6.51 s 0.024295 0.648 s 0.031179
AMT_GOODS_PRICE 6.95 s 0.056923 0.401 s 0.092032
NAME_HOUSING_TYPE (C) 3.57 s 0.015055 0.140 s 0.015055
REGION_POPULATION_RELATIVE 4.33 s 0.026578 0.392 s 0.035567
DAYS_BIRTH 5.18 s 0.081270 0.564 s 0.086539
OWN_CAR_AGE 4.85 s 0.021429 0.055 s 0.021890
OCCUPATION_TYPE (C) 4.24 s 0.077606 0.201 s 0.079540
APARTMENTS_AVG 5.61 s 0.032247 (*) 0.184 s 0.032415
BASEMENTAREA_AVG 5.14 s 0.022320 0.119 s 0.022639
YEARS_BUILD_AVG 4.49 s 0.016033 0.055 s 0.016932
EXT_SOURCE_2 5.21 s 0.298463 0.606 s 0.321417
EXT_SOURCE_3 5.08 s 0.316352 0.303 s 0.334975
TOTAL 84.47 s 1.130907 5.087 s 1.247756

(C): categorical variable. (*): max p-value between consecutive bins > 0.05.

Binning of variables with a peak or valley monotonicity trend can benefit from monotonic_trend="auto_heuristic", at the expense of a suboptimal solution in some cases:

Variable auto time auto IV heuristic time heuristic IV
AMT_INCOME_TOTAL 0.363 s 0.011705 0.322 s 0.011705
AMT_CREDIT 0.634 s 0.059311 0.469 s 0.058643
AMT_ANNUITY 0.648 s 0.031179 0.505 s 0.031179
AMT_GOODS_PRICE 0.401 s 0.092032 0.299 s 0.092032
REGION_POPULATION_RELATIVE 0.392 s 0.035567 0.244 s 0.035567
TOTAL 2.438 s 0.229794 1.839 s 0.229126

CPU time is reduced by 25% while losing less than 1% in IV. The difference grows with the number of bins — see the large-scale tutorial.


Contributing

Contribute algorithms and features upstream. New capabilities, bug fixes in the core formulation and documentation improvements belong at guillermo-navas-palencia/optbinning, where they benefit every user.

This fork accepts only what is in scope for it: Python and dependency compatibility, packaging, and keeping the test suite green. Before opening an issue here, please check whether it reproduces upstream.

Who uses OptBinning?

The following list is maintained upstream and reproduced here; to be added to it, send a PR to the upstream repository.

Jeitto · Bilendo · Aplazame · Praelexis Credit · ING · DBRS Morningstar · Loginom · Risika · Tamara · BBVA AI Factory · N26 · Home Credit International · Farm Credit Canada

Citation

If you use OptBinning in your research or work, please cite the original author's papers — not this fork:

@article{Navas-Palencia2020OptBinning,
  title     = {Optimal binning: mathematical programming formulation},
  author    = {Guillermo Navas-Palencia},
  year      = {2020},
  eprint    = {2001.08025},
  archivePrefix = {arXiv},
  primaryClass = {cs.LG},
  volume    = {abs/2001.08025},
  url       = {http://arxiv.org/abs/2001.08025},
}

@article{Navas-Palencia2021Counterfactual,
  title     = {Optimal Counterfactual Explanations for Scorecard modelling},
  author    = {Guillermo Navas-Palencia},
  year      = {2021},
  eprint    = {2104.08619},
  archivePrefix = {arXiv},
  primaryClass = {cs.LG},
  volume    = {abs/2104.08619},
  url       = {http://arxiv.org/abs/2104.08619},
}

License

Apache License 2.0 — see LICENSE.

Copyright (c) 2019-2025 Guillermo Navas-Palencia. Fork modifications are released under the same license.

Metadata

Release files for optbinning-slim 0.22.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for optbinning-slim 0.22.0
File Size Uploaded
optbinning_slim-0.22.0.tar.gz 1.4 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for optbinning-slim 0.22.0
File Interpreter ABI Platform
optbinning_slim-0.22.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.6 MB

Release files / optbinning_slim-0.22.0.tar.gz

Download URL optbinning_slim-0.22.0.tar.gz
Size 1.4 MB
Tags Source
SHA-256 checksum
How to use checksums
d60edf92d200f9536f318a6f749185cb1f774151ca9f2d6791a4723d56af829a
BLAKE2b-256 checksum
How to use checksums
626c85d9fd4b17211c842c1c451712b2bdbe41020d6e210a477bc0f7065d2794
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / optbinning_slim-0.22.0-py3-none-any.whl

Download URL optbinning_slim-0.22.0-py3-none-any.whl
Size 225.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ad1a2788cda8c981068966c2132264ef5b5ae63f4deac267825f90a8f5508228
BLAKE2b-256 checksum
How to use checksums
0c75810b3662df490e85b4d7cc2394b84ac36d539078969f853e08be142f950f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release history Release notifications | RSS feed

0.23.0

2 release files

This release

0.22.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page