# Parity tests for the TabICL feature preprocessing (R/tabicl-preprocess.R) # against scikit-learn. Fixtures are generated by dev/tabicl/dump_preprocess.py: # fit on the training rows, transform a held-out set that includes an outlier. # The Yeo-Johnson lambdas come from an optimizer but match scipy's Brent to ~1e-7, # so all comparisons use the float32 storage tolerance. # Load a preprocessing fixture as plain R matrices / vectors. tabicl_load_prep <- function(name) { f <- tabicl_load_fixture(name) lapply(f, function(t) { arr <- as.array(t) if (length(dim(t)) == 1L) as.numeric(arr) else as.matrix(arr) }) } test_that("tabicl standard scaler matches sklearn", { skip_if_no_tabicl_fixtures("prep_standard_scaler") f <- tabicl_load_prep("prep_standard_scaler") p <- brulee:::tabicl_standard_scaler_fit(f$x_fit) expect_lt(max(abs(p$mean - f$mean)), 1e-5) expect_lt(max(abs(p$scale - f$scale)), 1e-5) out <- brulee:::tabicl_standard_scaler_transform(p, f$x_apply) expect_lt(max(abs(out - f$out)), 1e-5) }) test_that("tabicl outlier remover matches sklearn", { skip_if_no_tabicl_fixtures("prep_outlier_remover") f <- tabicl_load_prep("prep_outlier_remover") p <- brulee:::tabicl_outlier_remover_fit(f$x_fit, threshold = 4.0) expect_lt(max(abs(p$lower - f$lower)), 1e-5) expect_lt(max(abs(p$upper - f$upper)), 1e-5) out <- brulee:::tabicl_outlier_remover_transform(p, f$x_apply) expect_lt(max(abs(out - f$out)), 1e-5) }) test_that("tabicl preprocessing pipeline (none) matches sklearn", { skip_if_no_tabicl_fixtures("prep_pipeline_none") f <- tabicl_load_prep("prep_pipeline_none") pp <- brulee:::tabicl_preprocess_fit(f$x_fit, normalization_method = "none") out <- brulee:::tabicl_preprocess_transform(pp, f$x_apply) expect_lt(max(abs(out - f$out)), 1e-5) }) test_that("tabicl preprocessing pipeline (Yeo-Johnson) matches sklearn", { skip_if_no_tabicl_fixtures("prep_pipeline_power") f <- tabicl_load_prep("prep_pipeline_power") pp <- brulee:::tabicl_preprocess_fit( f$x_fit, normalization_method = "YeoJohnson" ) expect_lt(max(abs(pp$normalizer$lambdas - f$lambdas)), 1e-5) out <- brulee:::tabicl_preprocess_transform(pp, f$x_apply) expect_lt(max(abs(out - f$out)), 1e-5) }) test_that("Yeo-Johnson transform keeps a matrix for a single row", { skip_on_cran() set.seed(396187) x_fit <- matrix(rnorm(40), ncol = 4) pp <- brulee:::tabicl_preprocess_fit( x_fit, normalization_method = "YeoJohnson" ) one_row <- brulee:::tabicl_preprocess_transform(pp, x_fit[1, , drop = FALSE]) expect_true(is.matrix(one_row)) expect_equal(dim(one_row), c(1L, ncol(x_fit))) multi <- brulee:::tabicl_preprocess_transform(pp, x_fit[1:2, , drop = FALSE]) expect_equal(one_row[1, ], multi[1, ]) }) test_that("unsupported normalization methods error", { skip_on_cran() x <- matrix(rnorm(40), ncol = 4) expect_snapshot( error = TRUE, brulee:::tabicl_preprocess_fit(x, normalization_method = "quantile") ) })