Quickstart

This page fits your first representation in a few minutes. It covers the two ways to use PreTab: the high-level Preprocessor that builds a full pipeline from a config, and the individual transformers that behave like any other scikit-learn step.

Install

pip install pretab

See Installation for optional extras such as language embeddings and LightGBM-based placement.

Fit a Preprocessor

The Preprocessor inspects a DataFrame, decides which columns are numerical and which are categorical, and applies a strategy per column. It returns a single stacked array by default, or a dict of per-feature blocks on request.

import numpy as np
import pandas as pd

from pretab import Preprocessor

rng = np.random.default_rng(0)
df = pd.DataFrame({
    "age": rng.integers(18, 65, size=200),
    "income": rng.normal(60_000, 15_000, size=200).astype(int),
    "experience": rng.integers(0, 40, size=200),
    "job": rng.choice(["nurse", "engineer", "scientist", "teacher"], size=200),
    "city": rng.choice(["Berlin", "Munich", "Hamburg", "Cologne"], size=200),
})
y = np.sin(df["age"] / 10) + df["income"] / 1e5 + rng.normal(0, 0.1, size=200)

config = {
    "age": "ple",              # supervised piecewise-linear encoding
    "income": "rbf",           # radial basis feature map
    "experience": "naturalspline",
    "job": "one-hot",
    "city": "int",             # integer (ordinal) codes
}
pre = Preprocessor(feature_preprocessing=config, task="regression", random_state=0)

# Fit and transform into a single stacked array
X = pre.fit_transform(df, y)
X.shape
(200, 26)

Tip

When no per-feature config is given, the Preprocessor falls back to its global numerical_method (default "ple") and categorical_method (default "int"). See Configuration for every knob.

Ask for a dict of per-feature blocks instead, for inspection or per-block downstream heads:

X_dict = pre.transform(df, return_array=False)   # {"num_age": ..., "cat_city": ...}
{'num_age': (200, 7), 'num_income': (200, 7), 'num_experience': (200, 7),
 'cat_job': (200, 4), 'cat_city': (200, 1)}

Inspect what was built

Every fitted representation is self-describing. Read the resolved layout, or trace each output column back to its source.

pre.get_feature_info(verbose=True)   # human-readable table of per-feature pipelines

lineage = pre.get_feature_lineage()  # one record per output column
lineage[0]
feature     kind         pipeline                          dim   cats
-----------------------------------------------------------------------
age         numerical    imputer -> minmax -> ple            7      -
income      numerical    imputer -> minmax -> rbf             7      -
experience  numerical    imputer -> minmax -> naturalspline   7      -
job         categorical  imputer -> onehot -> to_float         4      4
city        categorical  imputer -> continuous_ordinal        1      5
FeatureLineage(output_feature='num_age_ple0', output_index=0, source_features=('age',),
               family='piecewise_linear', component='interval', component_index=0,
               uses_target=True, is_interaction=False)

The lineage covers every output column, and the names line up with get_feature_names_out. See Outputs and inspection for the full contract.

Use a transformer on its own

Every strategy is also importable from pretab.transformers and follows the scikit-learn API, so it drops into a Pipeline or ColumnTransformer.

import numpy as np

from pretab.transformers import PLETransformer

x = np.random.randn(200, 1)
y = np.random.randn(200)

x_ple = PLETransformer(output_dim=15, task="regression").fit_transform(x, y)
x_ple.shape[1]   # number of piecewise-linear bins
15

Note

PLETransformer is supervised: it reads the target y during fit to place its bin edges. Always pass y when fitting it, or any pipeline that contains it. See Target awareness.

Spline families that carry a smoothness penalty expose it through get_penalty_matrix():

import numpy as np

from pretab.transformers import NaturalCubicSplineTransformer

x = np.random.randn(200, 1)
spline = NaturalCubicSplineTransformer(output_dim=8)
spline.fit_transform(x)

penalty = spline.get_penalty_matrix()   # integrated-curvature penalty for GAM-style fitting
(200, 8)   # spline.fit_transform(x).shape
(8, 8)     # penalty.shape

The multivariate thin-plate spline models several columns jointly and is sized by n_components rather than output_dim:

import numpy as np

from pretab.transformers import ThinPlateSplineTransformer

x = np.random.randn(200, 2)              # two input columns, modelled together
tp = ThinPlateSplineTransformer(n_components=10)
features = tp.fit_transform(x)
penalty = tp.get_penalty_matrix()
(200, 10)   # features.shape
(10, 10)    # penalty.shape

Warning

ThinPlateSplineTransformer.get_penalty_matrix() is experimental: the retained eigenvalues are not guaranteed non-negative, so the returned penalty is not guaranteed positive semi-definite. Calling it emits a ConfigWarning to make this explicit.

Next steps