Skip to content

fix(preprocessor): reject an unrecognized scaling value #35

Description

@ChrisW09

Summary

Preprocessor(scaling=...) accepts any string. An unrecognized value silently produces a
pipeline with no scaler at all — no error, no warning. A typo therefore disables the
scaling step rather than reporting it, while the same typo in numerical_method raises.

Reproduction

from pretab.pipeline import get_numerical_transformer_steps

for s in ["minmax", "MinMax", "zscore", "not_a_scaler", "minmaxx", "none", None]:
    print(f"{s!r:15} -> {[n for n, _ in get_numerical_transformer_steps('ple', scaling=s)]}")
'minmax'        -> ['imputer', 'minmax', 'ple']
'MinMax'        -> ['imputer', 'minmax', 'ple']
'zscore'        -> ['imputer', 'scaler', 'ple']
'not_a_scaler'  -> ['imputer', 'ple']          <- silently unscaled
'minmaxx'       -> ['imputer', 'ple']          <- silently unscaled
'none'          -> ['imputer', 'ple']          <- intentional
None            -> ['imputer', 'ple']          <- intentional

End to end, Preprocessor(scaling="minmaxx").fit(df, y) completes without complaint and
produces unscaled features.

Expected

An unrecognized scaling value raises InvalidParamError listing the valid options, exactly
as numerical_method and categorical_method already do. None and "none" keep meaning
"no scaling".

Actual

Anything that isn't a recognized scaler is treated as "no scaling".

Root cause

pretab/pipeline/numerical.py:131-135:

if scaling is not None:
    scaling = resolve_method(scaling, NUMERICAL_METHODS, NUMERICAL_ALIASES)
if scaling in scalers and scaling != method:
    steps.append(scalers[scaling])

resolve_method returns the input lowercased when it recognizes nothing, and the membership
test then just fails. Contrast with the method name a few lines below, which is explicitly
validated against NUMERICAL_METHODS and raises.

Suggested fix

Validate after resolution, allowing the two documented no-op spellings:

if scaling is not None:
    scaling = resolve_method(scaling, NUMERICAL_METHODS, NUMERICAL_ALIASES)
    if scaling not in scalers and scaling != "none":
        raise invalid_param_error(
            "get_numerical_transformer_steps", "scaling", scaling,
            "must name a scaler or disable scaling",
            valid={*scalers, "none", None},
        )

This matters more than a typical typo guard because the failure is invisible: the fit
succeeds, the widths are unchanged, and only the numeric scale of the features differs — so
the mistake surfaces (if at all) as a quietly worse model.

Environment

  • pretab 0.1.0 (main @ 51c3043)
  • Python 3.11.15, numpy 2.4.6, pandas 2.3.3, scikit-learn 1.9.0, scipy 1.17.1
  • macOS (darwin 25.5.0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions