API: preprocessing.encoding
skyulf.preprocessing.encoding
Encoding nodes package.
Split from a single 832-LOC module into per-encoder files
_common.py — shared helpers (detect_categorical_columns, _exclude_target_column, …) one_hot.py — OneHotEncoder ordinal.py — OrdinalEncoder label.py — LabelEncoder target.py — TargetEncoder hash.py — HashEncoder dummy.py — DummyEncoder woe.py — WOEEncoder (Weight-of-Evidence / Information Value)
All public names are re-exported here so existing imports such as
from skyulf.preprocessing.encoding import OneHotEncoderCalculator
continue to work unchanged.
DummyEncoderApplier
Bases: BaseApplier
Replace each categorical column with one <col>_<category> indicator column.
The originals are always dropped. Parity depends on both engines rendering
a value to the same string before comparing it with the learned
categories — one rule, implemented per engine by _pandas_col_to_str
and _polars_col_to_str_expr, which is a function of the value alone so
a category cannot stop matching because of what else shares its batch. A
value unseen at fit time yields an all-zero row rather than raising.
Generated names that duplicate another indicator or a retained input
column raise ValueError before output construction.
Version 1 artifacts render booleans and datetimes consistently across engines, including nanoseconds and timezone-aware instants. Midnight naive datetimes share date keys. Literal strings are unchanged. Unversioned artifacts retain their original rendering; refit the encoder and downstream model to obtain the portable category contract.
Source code in skyulf-core/skyulf/preprocessing/encoding/dummy.py
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | |
apply(X, y, params)
Dispatch to the engine-specific dummy encoding, forwarding (X, y) when present.
Source code in skyulf-core/skyulf/preprocessing/encoding/dummy.py
253 254 255 256 257 258 259 260 | |
inference_capability(state, *, engine)
staticmethod
Keep legacy pandas batch rendering visible in the local context declaration.
Source code in skyulf-core/skyulf/preprocessing/encoding/dummy.py
243 244 245 246 247 248 249 250 251 | |
validate_inference_state(raw)
staticmethod
Inspect saved categories without deriving a vocabulary from inference rows.
Source code in skyulf-core/skyulf/preprocessing/encoding/dummy.py
230 231 232 233 234 235 236 237 238 239 240 241 | |
DummyEncoderCalculator
Bases: BaseCalculator
Learn the sorted category list for each resolved categorical column.
The target column is excluded first: dummy encoding replaces the column it
encodes with several derived ones, which would break a downstream
Feature/Target Split. Nulls and float NaN are dropped before the list is
built, so they never become a category. An explicit columns: [] yields
an empty artifact so the applier no-ops.
Source code in skyulf-core/skyulf/preprocessing/encoding/dummy.py
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | |
fit(X, y, config)
Short-circuit an explicit empty column selection, else learn the categories.
Source code in skyulf-core/skyulf/preprocessing/encoding/dummy.py
332 333 334 335 336 337 338 339 340 341 342 343 344 | |
HashEncoderApplier
Bases: BaseApplier
Replace each categorical column's values in place with a bucket index.
Buckets run over [0, n_features). No vocabulary is learned, so the same
artifact handles values never seen at fit time — at the cost of collisions,
which the hashing trick accepts by design. Both engines must agree on the
bucket, which is why they share _stable_hash (blake2b) instead of using
polars' native hash(): deployment always crosses engines, so a
divergence would corrupt every production encoding. Version 2 normalizes
missing and numeric scalars per value, keeping literal strings distinct.
Older normalization versions retain their original bucket assignments.
Source code in skyulf-core/skyulf/preprocessing/encoding/hash.py
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
apply(X, y, params)
Dispatch to the engine-specific hashing, forwarding (X, y) only when y exists.
Source code in skyulf-core/skyulf/preprocessing/encoding/hash.py
170 171 172 173 174 175 176 177 | |
inference_capability(state, *, engine)
staticmethod
Describe fixed hashing while preserving legacy pandas rendering dependencies.
Source code in skyulf-core/skyulf/preprocessing/encoding/hash.py
160 161 162 163 164 165 166 167 168 | |
validate_inference_state(raw)
staticmethod
Inspect saved hashing choices without computing buckets or coercing scalars.
Source code in skyulf-core/skyulf/preprocessing/encoding/hash.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
HashEncoderCalculator
Bases: BaseCalculator
Resolve which columns to hash and how many buckets to use.
No vocabulary is learned — hashing is stateless, so the artifact is just
the column set plus n_features. The target column is excluded because
hash encoding overwrites the column it encodes. An explicit
columns: [], or auto-detection finding nothing, yields an empty
artifact so the applier no-ops.
Source code in skyulf-core/skyulf/preprocessing/encoding/hash.py
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | |
fit(X, y, config)
Build the artifact, auto-detecting categorical columns when none are named.
Source code in skyulf-core/skyulf/preprocessing/encoding/hash.py
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | |
infer_output_schema(input_schema, config)
Pass the input schema through: bucket indices replace values in place.
Source code in skyulf-core/skyulf/preprocessing/encoding/hash.py
217 218 219 220 221 222 223 224 225 | |
LabelEncoderApplier
Bases: BaseApplier
Replace categorical values in place with the integer ids their fitted encoder assigned.
New feature artifacts use typed scalar keys: integral floats match their
integer category without matching literal numeric strings. Legacy artifacts
retain their original string lookup. Values unseen at fit time map to
missing_code. Target encoders retain their existing string-label behavior.
Encoded targets are native Series for the feature engine; pandas Series keep
their index and all native Series keep their name. Unencoded targets pass
through unchanged, including lists and NumPy arrays.
Source code in skyulf-core/skyulf/preprocessing/encoding/label.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | |
apply(X, y, params)
Dispatch to the engine-specific encode, forwarding (X, y) only when y exists.
Source code in skyulf-core/skyulf/preprocessing/encoding/label.py
212 213 214 215 216 217 218 219 220 | |
inference_capability(state, *, engine)
staticmethod
Declare fixed lookups while retaining legacy feature rendering dependencies.
Source code in skyulf-core/skyulf/preprocessing/encoding/label.py
202 203 204 205 206 207 208 209 210 | |
validate_inference_state(raw)
staticmethod
Inspect native learned classes without normalizing the fitted artifact.
Source code in skyulf-core/skyulf/preprocessing/encoding/label.py
189 190 191 192 193 194 195 196 197 198 199 200 | |
LabelEncoderCalculator
Bases: BaseCalculator
Fit one LabelEncoder per named column, plus one for the target when it qualifies.
Unlike its sibling encoders this node deliberately does not auto-detect
feature columns: an empty columns means "encode the target only",
mirroring sklearn's convention that LabelEncoder is a 1-D label
transformer and OrdinalEncoder is the tool for feature columns. Fitting
zero encoders logs a warning rather than passing a silent no-op downstream.
Source code in skyulf-core/skyulf/preprocessing/encoding/label.py
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | |
fit(X, y, config)
Fit the encoders on the frame's own engine, forwarding y when present.
Source code in skyulf-core/skyulf/preprocessing/encoding/label.py
413 414 415 416 417 418 419 420 421 422 423 424 | |
infer_output_schema(input_schema, config)
Pass the input schema through: encoded columns keep their name and position.
Source code in skyulf-core/skyulf/preprocessing/encoding/label.py
405 406 407 408 409 410 411 | |
OneHotEncoderApplier
Bases: BaseApplier
Expand each categorical column into its one-hot indicator columns.
Parity here comes from both engines transforming through the same fitted
sklearn encoder carried in the artifact, not from two parallel
implementations. Nulls are filled with the sentinel token before
transforming, which only lines up when include_missing was set at fit
time too — the encoder knows that level solely if it saw it. Indicator
columns are concatenated on and the originals dropped unless
drop_original is false. Generated names must be unique and must not
collide with retained input columns; conflicts raise ValueError.
New artifacts escape literal missing tokens and escape-prefixed strings;
unversioned artifacts retain their original missing-value transformation.
An empty artifact declares identity replay only for an explicit empty
column selection with a validated recipe.
Source code in skyulf-core/skyulf/preprocessing/encoding/one_hot.py
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | |
apply(X, y, params)
Dispatch to the engine-specific transform, forwarding (X, y) only when present.
Source code in skyulf-core/skyulf/preprocessing/encoding/one_hot.py
209 210 211 212 213 214 215 216 | |
resolve_fitted_config(raw, state)
staticmethod
Bind inference configuration to this node's inspected fitted artifact.
Source code in skyulf-core/skyulf/preprocessing/encoding/one_hot.py
202 203 204 205 206 207 | |
validate_fitted_state(raw)
staticmethod
Inspect this node's supported saved state without fitting or applying data.
Source code in skyulf-core/skyulf/preprocessing/encoding/one_hot.py
197 198 199 200 | |
OneHotEncoderCalculator
Bases: BaseCalculator
Fit a sklearn OneHotEncoder on the resolved categorical columns.
The target column is excluded before fitting: one-hot replaces the column
it encodes with several derived ones, which would break a downstream
Feature/Target Split. An explicit columns: [], or auto-detection
finding no categorical columns, yields an empty artifact so the applier
no-ops. Degenerate columns (zero categories, or one category with
drop_first) are warned about rather than silently producing nothing.
Source code in skyulf-core/skyulf/preprocessing/encoding/one_hot.py
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | |
fit(X, y, config)
Short-circuit an explicit empty column selection, else fit on the frame's own engine.
Source code in skyulf-core/skyulf/preprocessing/encoding/one_hot.py
367 368 369 370 371 372 373 374 375 376 377 378 379 | |
OrdinalEncoderApplier
Bases: BaseApplier
Replace categorical values in place with fitted ordinal indices, target included.
Features use the shared encoder_object and versioned scalar keys; y
uses a separate __target__ encoder with its existing string-label rules.
Older feature artifacts retain their original string lookup. An unseen
value becomes unknown_value unless handle_unknown is "error".
Encoded output is float32, not integer.
Source code in skyulf-core/skyulf/preprocessing/encoding/ordinal.py
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | |
apply(X, y, params)
Dispatch to the engine-specific encode, forwarding (X, y) only when y exists.
Source code in skyulf-core/skyulf/preprocessing/encoding/ordinal.py
288 289 290 291 292 293 294 295 296 | |
inference_capability(state, *, engine)
staticmethod
Describe saved ordinal lookups without enabling worker execution.
Source code in skyulf-core/skyulf/preprocessing/encoding/ordinal.py
275 276 277 278 279 280 281 282 283 284 285 286 | |
validate_inference_state(raw)
staticmethod
Inspect feature and optional target encoders without changing lookup provenance.
Source code in skyulf-core/skyulf/preprocessing/encoding/ordinal.py
247 248 249 250 251 252 253 254 255 256 257 258 | |
OrdinalEncoderCalculator
Bases: BaseCalculator
Fit an ordinal encoder for the features and, when split out, for the target.
Picking no feature columns is not a no-op here — unlike its sibling
encoders, this node still fits a target encoder when y is available.
The target is encoded only when y exists and the configured target name
is listed in columns but absent from X, i.e. it has already been
split away. categories_order supplies an explicit ordering, and the
target reads the last row of an n_features + 1 row table.
Source code in skyulf-core/skyulf/preprocessing/encoding/ordinal.py
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 | |
fit(X, y, config)
Fit the encoders on the frame's own engine, forwarding y when present.
Source code in skyulf-core/skyulf/preprocessing/encoding/ordinal.py
520 521 522 523 524 525 526 527 528 529 530 531 | |
infer_output_schema(input_schema, config)
Pass the input schema through: encoded columns keep their name and position.
Source code in skyulf-core/skyulf/preprocessing/encoding/ordinal.py
512 513 514 515 516 517 518 | |
TargetEncoderApplier
Bases: BaseApplier
Replace categorical columns with the target statistics the fitted encoder learned.
Both engines transform through the same sklearn TargetEncoder carried in
the artifact, so parity comes from sharing it. The output shape follows the
target type: binary and regression targets are encoded in place, while a
multiclass target drops the originals and emits one {col}_cls{i} column
per class. Multiclass output names must not collide with retained columns;
conflicts raise ValueError before any input values are replaced.
Source code in skyulf-core/skyulf/preprocessing/encoding/target.py
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | |
apply(X, y, params)
Dispatch to the engine-specific transform, forwarding (X, y) only when present.
Source code in skyulf-core/skyulf/preprocessing/encoding/target.py
211 212 213 214 215 216 217 218 | |
inference_capability(state, *, engine)
staticmethod
Describe saved target-statistic lookups without refitting or admitting workers.
Source code in skyulf-core/skyulf/preprocessing/encoding/target.py
203 204 205 206 207 208 209 | |
validate_inference_state(raw)
staticmethod
Inspect the saved full-data encoder while leaving cross-fitted training values alone.
Source code in skyulf-core/skyulf/preprocessing/encoding/target.py
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | |
TargetEncoderCalculator
Bases: BaseCalculator
Fit a sklearn TargetEncoder against y, cross-fitting the training rows.
A target is mandatory: with no y the node logs a warning and returns an
empty artifact rather than failing. The target column is excluded from the
encoded set, since encoding it against itself is degenerate. This calculator
also satisfies TrainTransformCalculatorProtocol, so the training split
receives out-of-fold encodings — a row's own target never leaks into its
feature — with the fold count capped by the smallest class count, while
held-out splits go through the plain applier.
Source code in skyulf-core/skyulf/preprocessing/encoding/target.py
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | |
fit(X, y, config)
Short-circuit an explicit empty column selection, else fit on the frame's own engine.
Source code in skyulf-core/skyulf/preprocessing/encoding/target.py
433 434 435 436 437 438 439 440 441 442 443 444 445 | |
fit_transform_train(df, config)
Fit sklearn TargetEncoder and cross-fit the pipeline training rows.
Source code in skyulf-core/skyulf/preprocessing/encoding/target.py
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 | |
infer_output_schema(input_schema, config)
Predict the schema only when target_type is explicitly binary or continuous.
Anything else — "auto" included — can resolve to multiclass at fit
time, which changes the column set in a data-dependent way, so None
is returned and callers fall back to runtime introspection.
Source code in skyulf-core/skyulf/preprocessing/encoding/target.py
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | |
WOEEncoderApplier
Bases: BaseApplier
Replace each category with the Weight-of-Evidence value learned for it.
Both engines look the category up in the same fitted mapping, keyed by the
scalar key of the value, and fall back to default for categories
never seen at fit time. Nulls are keyed as the literal "nan" on both
sides, so a missing category gets its own learned WOE instead of always
taking the default (F-28). New artifacts distinguish numeric values from
literal strings; older artifacts preserve their original string keys.
Encoded columns become float.
Source code in skyulf-core/skyulf/preprocessing/encoding/woe.py
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
apply(X, y, params)
Dispatch to the engine-specific WOE lookup, forwarding (X, y) only when present.
Source code in skyulf-core/skyulf/preprocessing/encoding/woe.py
162 163 164 165 166 167 168 169 | |
inference_capability(state, *, engine)
staticmethod
Describe fixed WOE category lookups without granting partition execution.
Source code in skyulf-core/skyulf/preprocessing/encoding/woe.py
149 150 151 152 153 154 155 156 157 158 159 160 | |
validate_inference_state(raw)
staticmethod
Inspect learned mappings and their metadata without relearning target statistics.
Source code in skyulf-core/skyulf/preprocessing/encoding/woe.py
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
WOEEncoderCalculator
Bases: BaseCalculator
Fit the WOE mapping and per-column Information Value from a binary target.
Supervised and binary-only: a target without exactly two classes logs a
warning and yields an empty artifact rather than failing. The target column
is excluded from the encoded set, since WOE computed against itself is
near-perfect separation. The math is engine-agnostic, so fit funnels both
engines through one narrow pandas boundary while apply stays in the
caller's engine. fit_transform_train cross-fits the training rows so a
row's own target never leaks into its encoding.
regularization adds a pseudocount to each observed category in each
target class. Class totals include regularization * n_categories so
both smoothed distributions sum to one. Missing feature values count as
a category; each cross-fitting complement uses its own observed categories.
Source code in skyulf-core/skyulf/preprocessing/encoding/woe.py
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | |
fit(X, y, config)
Short-circuit an explicit empty column selection, else fit via the shared boundary.
Both engine keys dispatch to the same _woe_fit: it converts to
pandas internally, so there is no engine-specific fit to choose between.
Source code in skyulf-core/skyulf/preprocessing/encoding/woe.py
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | |
fit_transform_train(df, config)
Fit the full-data WOE artifact and cross-fit the training rows.
Source code in skyulf-core/skyulf/preprocessing/encoding/woe.py
409 410 411 412 413 414 415 416 417 418 419 420 421 | |
infer_output_schema(input_schema, config)
Pass the input schema through: WOE values replace the source columns in place.
Source code in skyulf-core/skyulf/preprocessing/encoding/woe.py
423 424 425 426 427 428 429 430 431 | |
detect_categorical_columns(df)
Auto-detect the string/categorical columns an encoder should target.
The fallback every encoder passes to resolve_columns when the user
configured no explicit column list: polars frames are matched on
Utf8/Categorical/Enum/Object dtypes, pandas frames via
select_dtypes on object/category/string — so "encode categoricals"
means the same thing on either engine.
Source code in skyulf-core/skyulf/preprocessing/encoding/_common.py
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |