Library / SDK
koaning/scikit-lego avatar
koaning/scikit-lego

scikit-lego: transformers and estimators that fill the gaps in scikit-learn pipelines

Extra blocks for scikit-learn pipelines.

1,411 stars131 forksPythonMIT

At a glance

What is it?
scikit-lego is an MIT-licensed Python package that adds transformers, metrics and models to scikit-learn. It is a grab bag rather than a framework, and that is both its value and its main cost.
Who is it for?
Adopt scikit-lego if you already build scikit-learn Pipeline objects and keep rewriting the same ColumnSelector, Thresholder or GroupedPredictor by hand; the package is small, MIT-licensed and installs with python -m pip install scikit-lego. Do not adopt it as a modelling framework, and do not expect a stable API across all of sklego.linear_model and sklego.meta, where the README itself labels several classes experimental.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 14 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap scikit-lego is trying to fill

The README opens with the motivation in plain terms: the authors found themselves writing custom transformers, metrics and models repeatedly, and wanted to consolidate that into one package with code quality and testing behind it. That is a narrow and honest goal. scikit-learn deliberately ships a small core, and the cost of that discipline is that a working data scientist ends up maintaining a private module of half-finished helpers. scikit-lego is an attempt to move those helpers somewhere they get reviewed, tested and versioned.

The audience is therefore specific. You need to be comfortable with the scikit-learn API already, because every class in the package is meant to be dropped into a Pipeline next to StandardScaler. The README example shows exactly that shape: a Pipeline with StandardScaler, then RandomAdder from sklego.preprocessing, then GMMClassifier from sklego.mixture. If you use a different modelling stack, or you prefer explicit functions over estimator objects, most of what is here will feel like ceremony. The project also states that it is not formally affiliated with scikit-learn, though it aims to adhere to their standards. Treat it as a third-party extension, not an official one.

What is actually in the package: modules, not a single abstraction

The feature list in the README is long and flat, and the flatness is the point. There is no unifying abstraction. What you get is a set of modules, each with a different theme.

sklego.preprocessing holds column-level transformers: ColumnSelector and TypeSelector pick columns by name or dtype, ColumnDropper removes one, ColumnCapper clips extremes, DictMapper maps categories to numbers, IdentityTransformer passes data through so pipelines can be concatenated, and RepeatingBasisFunction does cyclical feature engineering aimed at time series. sklego.meta holds wrappers that change how a model is trained or how its output is used: Thresholder lets you grid search the decision threshold, EstimatorTransformer turns a model prediction into a feature, GroupedPredictor and GroupedTransformer split data into groups and fit one model or transformer per group, DecayEstimator applies decay to sample_weight, and ZeroInflatedRegressor combines a classifier with a regressor.

Then there is a fairness and mixture cluster. DemographicParityClassifier and EqualOpportunityClassifier are logistic classifiers with constraints baked into the fit. GMMClassifier, BayesianGMMClassifier, GMMOutlierDetector and BayesianGMMOutlierDetector wrap Gaussian mixtures into the classifier and outlier-detector interfaces. Finally sklego.datasets provides loaders such as load_penguins, load_abalone and load_arrests, plus fetch_creditcard, which pulls a fraud dataset from openml. The dataset loaders are teaching material, and they are useful precisely because they are small and well known.

Installation and the import paths you will actually type

Installation is one of two commands. The README gives python -m pip install scikit-lego for pip users and conda install -c conda-forge scikit-lego for conda users. For contributing, the documented path is to clone the repository and run python -m pip install -e ".[dev]" followed by python setup.py develop. That second command is worth noting: setup.py develop is the legacy editable-install route, and its presence in the README suggests the development workflow has not been modernised to a single tool.

Imports follow scikit-learn conventions. The README's usage block imports RandomAdder from sklego.preprocessing and GMMClassifier from sklego.mixture, then wires them into a Pipeline. The same pattern applies across the feature list: sklego.meta.Thresholder, sklego.linear_model.QuantileRegression, sklego.model_selection.GroupTimeSeriesSplit, sklego.pandas_utils.add_lags. Note that sklego.pandas_utils and sklego.datasets sit outside the estimator API. add_lags mutates a pandas DataFrame and log_step is a decorator for logging pipeline steps, so those two are utilities rather than pipeline components and will not survive a joblib serialisation round trip the way a transformer will.

The fairness estimators are the most opinionated part, and the least ordinary

Most of scikit-lego is convenience. DemographicParityClassifier and EqualOpportunityClassifier are not. They are logistic classifiers with a fairness constraint built into the optimisation rather than applied as a post-processing step, which means the constraint changes the fitted coefficients and therefore the predictions for every row, not just the rows near a decision boundary.

That distinction matters when you compare against the usual alternative, which is to train an ordinary classifier and then adjust thresholds per group afterwards. Post-processing keeps the underlying model interpretable and lets you choose the trade-off after seeing the accuracy cost. A constrained fit folds the trade-off into training, so you cannot inspect the unconstrained model at all. The README lists both classes without stating how the constraint is enforced or what happens when the constrained problem has no feasible solution. If you plan to use them, that is the first thing to check in the documentation, because a constrained logistic regression that fails to converge will look like a normal convergence warning unless you read it carefully.

Where the package stops being the right tool

The README labels several items experimental: DeadZoneRegressor, ConfusionBalancer, SubjectiveClassifier and OutlierRemover. That word is doing real work. An experimental class in a package with a 0.9.x version number can change signature between minor releases, and the release history shows a steady cadence of patch releases (0.9.8, 0.9.9, 0.9.10 within roughly seven months). Pin the version in your requirements file if you build on anything marked experimental.

The deeper limitation is scope. This is a collection, so there is no guarantee that the class you need exists, and no guarantee that two classes in different modules compose cleanly. GroupedPredictor and Thresholder both change how predictions are produced; nesting them raises questions about which one sees the threshold and which one sees the group split, and the README does not answer that. Similarly, several transformers exist to work around scikit-learn's historical handling of pandas, and as scikit-learn itself improves column handling, some of these become redundant. Nothing in the material indicates a deprecation policy for classes that scikit-learn has since absorbed.

A real alternative, and how the approach differs

The obvious alternative is to keep the custom code in your own repository, which is what the authors were doing before they started the project. The difference is not features, it is maintenance surface. Your private module has exactly the transformers you wrote, with your naming and your edge cases, and no release schedule to track. scikit-lego gives you tested implementations plus the obligation to upgrade.

A second alternative, for the fairness estimators specifically, is to use scikit-learn's own model plus a post-processing step you control, or a dedicated fairness library. The trade-off is the one described above: constraint inside the fit versus adjustment after it. For the preprocessing pieces, the nearest alternative is often scikit-learn's own ColumnTransformer with a callable selector, which covers the ColumnSelector and TypeSelector use cases without an extra dependency. Where scikit-lego earns its place is in the pieces scikit-learn does not ship at all: Thresholder for grid searching a decision threshold, GroupedPredictor for per-group fits, ZeroInflatedRegressor, and the GMM-based classifiers and outlier detectors.

Maintenance, licensing and what to check before you commit

The licence is MIT, which permits commercial use and modification provided the copyright notice and permission notice are retained. That is a permissive licence, and it is the same family as scikit-learn's BSD licence, so there is no copyleft obligation on your own code. This is a description of the licence text, not legal advice; if your organisation has a policy on third-party dependencies, route it through whoever owns that policy.

On maintenance, the repository is not archived, the default branch is main, and the most recent push recorded is 2026-09-01, with v0.9.10 released 2026-08-30. The version number still starts with zero, which is a signal about API stability rather than about activity. The README notes contributions from around the globe and that the project began as a collaboration between companies in the Netherlands, initially as a teaching tool for contributing to open source. That origin explains the breadth of the feature list and also why some entries read as one person's solution to one person's problem.

Before adopting, do three concrete things. Open the documentation site and read the page for the specific class you intend to use, since the README lists names without parameters. Check the release notes for the version you pin, because the README does not document breaking changes. And run your own pipeline end to end with the class in place, because the README gives one usage example and it does not exercise the meta estimators, the fairness classifiers or the grouped models.

Editorial conclusion

Adopt scikit-lego if you already build scikit-learn Pipeline objects and keep rewriting the same ColumnSelector, Thresholder or GroupedPredictor by hand; the package is small, MIT-licensed and installs with python -m pip install scikit-lego. Do not adopt it as a modelling framework, and do not expect a stable API across all of sklego.linear_model and sklego.meta, where the README itself labels several classes experimental. Before committing, open the documentation page for the specific class you want, check whether it appears in the current release notes, and read its docstring for the parameters the README does not list.

Official sources

  1. koaning/scikit-lego on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes