{"id":45024745,"url":"https://github.com/chentahung/monotonic-optimal-binning","last_synced_at":"2026-02-19T03:02:27.457Z","repository":{"id":178981147,"uuid":"552802266","full_name":"ChenTaHung/Monotonic-Optimal-Binning","owner":"ChenTaHung","description":"Monotonic Optimal Binning algorithm is a statistical approach to transform continuous variables into optimal and monotonic categorical variables.","archived":false,"fork":false,"pushed_at":"2025-11-06T17:40:47.000Z","size":20842,"stargazers_count":17,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-06T19:20:39.115Z","etag":null,"topics":["credit","credit-card-fraud","credit-risk","data-discretization","datapreprocessing","feature-engineering","mob","monotone","monotone-optimal-binning","monotonic","monotonic-optimal-binning","pava","pool-adjacent-violators","python","risk","risk-management","statistics"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/MOBPY/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ChenTaHung.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-10-17T08:50:02.000Z","updated_at":"2025-11-06T17:40:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"1007dec0-b1fa-4306-a2cd-33dbafabd5dc","html_url":"https://github.com/ChenTaHung/Monotonic-Optimal-Binning","commit_stats":null,"previous_names":["chentahung/monotonic-optimal-binning"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/ChenTaHung/Monotonic-Optimal-Binning","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChenTaHung%2FMonotonic-Optimal-Binning","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChenTaHung%2FMonotonic-Optimal-Binning/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChenTaHung%2FMonotonic-Optimal-Binning/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChenTaHung%2FMonotonic-Optimal-Binning/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ChenTaHung","download_url":"https://codeload.github.com/ChenTaHung/Monotonic-Optimal-Binning/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChenTaHung%2FMonotonic-Optimal-Binning/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29601502,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T02:50:40.506Z","status":"ssl_error","status_checked_at":"2026-02-19T02:50:26.316Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["credit","credit-card-fraud","credit-risk","data-discretization","datapreprocessing","feature-engineering","mob","monotone","monotone-optimal-binning","monotonic","monotonic-optimal-binning","pava","pool-adjacent-violators","python","risk","risk-management","statistics"],"created_at":"2026-02-19T03:02:23.856Z","updated_at":"2026-02-19T03:02:27.451Z","avatar_url":"https://github.com/ChenTaHung.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1\u003e\u003cp align=\"center\"\u003e\u003cstrong\u003eMonotonic-Optimal-Binning\u003c/strong\u003e\u003c/p\u003e\u003c/h1\u003e\n\n\u003ch2\u003e\u003cp align=\"center\"\u003eMOBPY - Monotonic Optimal Binning for Python\u003c/p\u003e\u003c/h2\u003e\n\n[![Run Tests](https://github.com/ChenTaHung/Monotonic-Optimal-Binning/actions/workflows/RunTests.yml/badge.svg?branch=main)](https://github.com/ChenTaHung/Monotonic-Optimal-Binning/actions/workflows/RunTests.yml)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![PyPI version](https://badge.fury.io/py/MOBPY.svg?refresh=1)](https://pypi.org/project/MOBPY/)\n\nA fast, deterministic Python library for creating **monotonic optimal bins** with respect to a target variable. MOBPY implements a stack-based Pool-Adjacent-Violators Algorithm (PAVA) followed by constrained adjacent merging, ensuring strict monotonicity and statistical robustness.\n\n## 🎯 Key Features\n\n- **⚡ Fast \u0026 Deterministic**: Stack-based PAVA with O(n) complexity, followed by O(k) adjacent merges\n- **📊 Monotonic Guarantee**: Ensures strict monotonicity (increasing/decreasing) between bins and target\n- **🔧 Flexible Constraints**: Min/max samples, min positives, min/max bins with automatic resolution\n- **📈 WoE \u0026 IV Calculation**: Automatic Weight of Evidence and Information Value for binary targets\n- **🎨 Rich Visualizations**: Comprehensive plotting functions for PAVA process and binning results\n- **♾️ Safe Edges**: First bin starts at -∞, last bin ends at +∞ for complete coverage\n\n## 📦 Installation\n\n```bash\npip install MOBPY\n```\n\nFor development installation:\n```bash\ngit clone https://github.com/ChenTaHung/Monotonic-Optimal-Binning.git\ncd Monotonic-Optimal-Binning\npip install -e .\n```\n\n## 🚀 Quick Start\n\n```python\nimport pandas as pd\nimport numpy as np\nfrom MOBPY import MonotonicBinner, BinningConstraints\nfrom MOBPY.plot import plot_bin_statistics, plot_pava_comparison\nimport matplotlib.pyplot as plt\n\ndf = pd.read_csv('/Users/chentahung/Desktop/git/mob-py/data/german_data_credit_cat.csv')\n# Convert default to 0/1 (original is 1/2)\ndf['default'] = df['default'] - 1\n\n# Configure constraints\nconstraints = BinningConstraints(\n    min_bins=4,           # Minimum number of bins\n    max_bins=6,           # Maximum number of bins\n    min_samples=0.05,     # Each bin needs at least 5% of total samples\n    min_positives=0.01    # Each bin needs at least 1% of total positive samples\n)\n\n# Create and fit the binner\nbinner = MonotonicBinner(\n    df=df,\n    x='Durationinmonth',\n    y='default',\n    constraints=constraints\n)\nbinner.fit()\n\n# Get binning results\nbins = binner.bins_()        # Bin boundaries\nsummary = binner.summary_()  # Detailed statistics with WoE/IV\ndisplay(summary)\n```\n\nOutput:\n```\n    bucket\t    count\tcount_pct\tsum\t    mean\t    std\t        min\t max\twoe\t        iv\n0\t(-inf, 9)\t94\t    9.4\t        10.0\t0.106383\t0.309980\t0.0\t 1.0\t1.241870\t0.106307\n1\t[9, 16)\t    337\t    33.7\t    79.0\t0.234421\t0.424267\t0.0\t 1.0\t0.335632\t0.035238\n2\t[16, 45)\t499\t    49.9\t    171.0\t0.342685\t0.475084\t0.0\t 1.0\t-0.193553\t0.019342\n3\t[45, +inf)\t70\t    7.0\t4       0.0\t    0.571429\t0.498445\t0.0\t 1.0\t-1.127082\t0.102180\n```\n\n## 📊 Visualization\n\nMOBPY provides comprehensive visualization of binning results:\n\n```python\n# Generate comprehensive binning analysis plot\nfig = plot_bin_statistics(binner)\nplt.show()\n```\n\n![Binning Analysis](doc/charts/bin_statistics.png)\n\n*The `plot_bin_statistics` function creates a multi-panel visualization showing:*\n- **Top Left**: Weight of Evidence (WoE) bars for each bin\n- **Top Right**: Event rate trend with sample distribution\n- **Bottom Left**: Sample distribution histogram\n- **Bottom Right**: Target distribution boxplots per bin\n\n## 🔬 Understanding the Algorithm\n\nMOBPY uses a two-stage approach:\n\n### Stage 1: PAVA (Pool-Adjacent-Violators Algorithm)\nCreates initial monotonic blocks by pooling adjacent violators:\n\n```python\nfrom MOBPY.plot import plot_pava_comparison\n\n# Visualize PAVA process\nfig = plot_pava_comparison(binner)\nplt.show()\n```\n\n![Pava Comparison](doc/charts/pava_comparison.png)\n\n### Stage 2: Constrained Merging\nMerges adjacent blocks to satisfy constraints while preserving monotonicity:\n\n```python\n# Check initial PAVA blocks vs final bins\nprint(f\"PAVA blocks: {len(binner.pava_blocks_())}\")\nprint(f\"Final bins: {len(binner.bins_())}\")\n\n\u003e PAVA blocks: 10\n\u003e Final bins: 4\n```\n\n## 🎛️ Advanced Configuration\n\n### Custom Constraints\n\n```python\n# Fractional constraints (adaptive to data size)\nconstraints = BinningConstraints(\n    max_bins=8,\n    min_samples=0.05,     # 5% of total samples\n    max_samples=0.30,     # 30% of total samples\n    min_positives=0.01    # 1% of positive samples\n)\n\n# Absolute constraints (fixed values)\nconstraints = BinningConstraints(\n    max_bins=5,\n    min_samples=100,      # At least 100 samples per bin\n    max_samples=500       # At most 500 samples per bin\n)\n```\n\n### Handling Special Values\n\n```python\n# Exclude special codes from binning\nage_binner = MonotonicBinner(\n    df=df,\n    x='Age',\n    y='default',\n    constraints= constraints,\n    exclude_values=[-999, -1, 0]  # Treat as separate bins\n).fit()\n```\n\n### Transform New Data\n\n```python\nnew_data = pd.DataFrame({'age': [25, 45, 65]})\n\n# Get bin assignments\nbins = age_binner.transform(new_data['age'], assign='interval')\nprint(bins)\n# Output:\n# 0    (-inf, 26)\n# 1      [35, 75)\n# 2      [35, 75)\n# Name: age, dtype: object\n\n# Get WoE values for scoring\nprint(age_binner.transform(new_data['age'], assign='woe'))\n# Output:\n# 0   -0.526748\n# 1    0.306015\n# 2    0.306015\n```\n\n## 📈 Use Cases\n\nMOBPY is ideal for:\n\n- **Credit Risk Modeling**: Create monotonic risk score bins for regulatory compliance\n- **Insurance Pricing**: Develop age/risk factor bands with clear premium progression\n- **Customer Segmentation**: Build ordered customer value tiers\n- **Feature Engineering**: Generate interpretable binned features for ML models\n- **Regulatory Reporting**: Ensure transparent, monotonic relationships in models\n\n## 📚 Documentation\n\n- [API Reference](docs/api_reference.md) - Complete API documentation\n- [Algorithm Details](docs/core) - Mathematical foundations\n- [Examples \u0026 Tutorials](examples/) - Jupyter notebooks with real-world examples\n\n## 🧪 Testing\n\n```bash\n# Run unit tests\npytest -vv -ignore-userwarnings -q\n```\n\n## 📖 Reference\n\n* [Mironchyk, Pavel, and Viktor Tchistiakov. *Monotone optimal binning algorithm for credit risk modeling.* (2017)](https://www.researchgate.net/profile/Viktor-Tchistiakov/publication/322520135_Monotone_optimal_binning_algorithm_for_credit_risk_modeling/links/5a5dd1a8458515c03edf9a97/Monotone-optimal-binning-algorithm-for-credit-risk-modeling.pdf)\n* [Smalbil, P. J. *The choices of weights in the iterative convex minorant algorithm.* (2015)](https://repository.tudelft.nl/islandora/object/uuid:5a111157-1a92-4176-9c8e-0b848feb7c30)\n* Testing Dataset 1: [German Credit Risk](https://www.kaggle.com/datasets/uciml/german-credit) from Kaggle\n* Testing Dataset 2: [US Health Insurance Dataset](https://www.kaggle.com/datasets/teertha/ushealthinsurancedataset) from Kaggle\n* GitHub Project: [Monotone Optimal Binning (SAS 9.4 version)](https://github.com/cdfq384903/MonotonicOptimalBinning)\n\n## 👥 Authors\n\n1. Ta-Hung (Denny) Chen\n   * LinkedIn: [https://www.linkedin.com/in/dennychen-tahung/](https://www.linkedin.com/in/dennychen-tahung/)\n   * E-mail: [denny20700@gmail.com](mailto:denny20700@gmail.com)\n\n2. Yu-Cheng (Darren) Tsai\n   * LinkedIn: [https://www.linkedin.com/in/darren-yucheng-tsai/](https://www.linkedin.com/in/darren-yucheng-tsai/)\n   * E-mail:\n\n3. Peter Chen\n   * LinkedIn: [https://www.linkedin.com/in/peterchentsungwei/](https://www.linkedin.com/in/peterchentsungwei/)\n   * E-mail: [peterwei20700@gmail.com](mailto:peterwei20700@gmail.com)\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchentahung%2Fmonotonic-optimal-binning","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchentahung%2Fmonotonic-optimal-binning","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchentahung%2Fmonotonic-optimal-binning/lists"}