c5tree 🌳
C5.0 Decision Tree Classifier for Python — a scikit-learn-compatible implementation of Ross Quinlan's C5.0 algorithm, with an optional native C++ numeric splitter.
Why C5.0?
scikit-learn's DecisionTreeClassifier uses CART (binary splits, Gini/entropy). C5.0 offers several advantages:
| Feature | CART (sklearn) | C5.0 (c5tree) |
|---|---|---|
| Split criterion | Gini / Entropy | Gain Ratio |
| Categorical splits | Binary only | Multi-way |
| Missing values | Requires imputation | Native support |
| Pruning | Cost-complexity | Pessimistic Error Pruning |
| Tree size | Often larger | Smaller, more interpretable |
Installation
pip install c5tree
Quick Start
from c5tree import C5Classifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
clf = C5Classifier(pruning=True, cf=0.25)
clf.fit(X_train, y_train)
print(f"Accuracy: {clf.score(X_test, y_test):.3f}")
print(f"Tree depth: {clf.get_depth()}")
print(f"Leaves: {clf.get_n_leaves()}")
Key Features
Gain Ratio Splitting
Corrects ID3's bias toward features with many distinct values by normalising information gain by split information.
Optional Native Acceleration
Numeric split evaluation uses an optional C++ extension through pybind11 when a compiler is available. Standard installs remain supported without a compiler and automatically use the equivalent Python implementation. This keeps C5.0 gain-ratio behavior while accelerating its hottest numeric operation; it is not a LightGBM or XGBoost model.
Native Missing Value Handling
No imputation needed. Missing instances are distributed fractionally across branches, weighted by the proportion of known instances going each way.
import numpy as np
X_with_missing = X.copy().astype(float)
X_with_missing[0, 2] = np.nan # inject a missing value
clf.fit(X_with_missing, y) # works out of the box
clf.predict(X_with_missing) # also works
Categorical Feature Support
Pass a pandas DataFrame and c5tree automatically detects object/category columns and applies multi-way splits:
import pandas as pd
df = pd.DataFrame({
"outlook": ["sunny", "overcast", "rainy", "sunny", "rainy"],
"humidity": [85, 65, 70, 95, 80],
"play": [0, 1, 1, 0, 1],
})
X = df[["outlook", "humidity"]]
y = df["play"]
clf = C5Classifier(pruning=False).fit(X, y)
Pessimistic Error Pruning
After the tree is grown, subtrees are replaced by leaves if the pessimistic error estimate of the subtree is no better than a single leaf. Controlled by the cf parameter.
# cf=0.25 → default, moderate pruning
# cf=0.05 → aggressive pruning, very small tree
# cf=0.50 → light pruning, larger tree
clf = C5Classifier(pruning=True, cf=0.05)
Human-Readable Tree
print(clf.text_report())
# [feature_2 <= 1.9000]
# left:
# → Predict: 0 [0: 1.00, 1: 0.00, 2: 0.00] (n=40.0)
# right:
# [feature_3 <= 1.7500]
# ...
Tested sklearn Compatibility
The tested estimator workflows include Pipelines, GridSearchCV, cross_val_score, and clone:
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV
pipe = Pipeline([
("scaler", StandardScaler()),
("clf", C5Classifier()),
])
param_grid = {"clf__cf": [0.05, 0.25, 0.50], "clf__max_depth": [None, 5, 10]}
search = GridSearchCV(pipe, param_grid, cv=5)
search.fit(X_train, y_train)
print(search.best_params_)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
max_depth |
int or None | None | Maximum tree depth |
min_samples_split |
int | 2 | Minimum samples to split a node |
min_samples_leaf |
int | 1 | Minimum samples at a leaf |
pruning |
bool | True | Enable pessimistic error pruning |
cf |
float | 0.25 | Confidence factor for pruning (0.05–0.50) |
min_gain_ratio |
float | 0.0 | Minimum gain ratio to make a split |
Running Tests
python -m pip install -e ".[dev]"
pytest tests/ -v --cov=c5tree
Building Packages
python -m pip install build
python -m build
The wheel includes the native C++ splitter when it can be compiled. Installing from source without a supported compiler still succeeds and uses the Python fallback. Binary wheels can be published for each supported operating system and Python version, as with LightGBM and XGBoost, so most users do not need a compiler.
Background
C5.0 is the successor to C4.5 and ID3, developed by Ross Quinlan. The algorithm was open-sourced in 2011 under the GPL licence. This package is a clean Python reimplementation that integrates C5.0-style splitting with the scikit-learn estimator API.
Reference: Quinlan, J.R. (1993). C4.5: Programs for Machine Learning. Morgan Kaufmann.
Contributing
Contributions are very welcome! Please open an issue before submitting a PR.
Licence
GPL-3.0-or-later License — see LICENSE.
Metadata
Release files for c5tree 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| c5tree-0.2.0.tar.gz | 29.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| c5tree-0.2.0-cp311-cp311-win_amd64.whl | CPython 3.11 | CPython 3.11 | Windows x86-64 | Details |
Total release size: 131.3 kB
Release files / c5tree-0.2.0.tar.gz
| Download URL | c5tree-0.2.0.tar.gz |
|---|---|
| Size | 29.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1e33ebdfc01246841b02734899ba387ce8f49901f7e6cdc50e413161992fd792
|
|
BLAKE2b-256 checksum How to use checksums |
5f113dbd8a8970946527cc3649439e66ea5dbc9b44c411d02f0cf94b087822c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.6
|
Release files / c5tree-0.2.0-cp311-cp311-win_amd64.whl
| Download URL | c5tree-0.2.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 101.5 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
0a29ae72a2ee312456407ea9f71bbec81d101b1d55983003446efef89eb96158
|
|
BLAKE2b-256 checksum How to use checksums |
084e92a707399add54067dd08cfbb89695ab27695a10fcdcfded140b67dfd251
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.6
|
Security for c5tree 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.