Different columns must be handled in different ways.
StandardScaler) work only on numeric columnsOneHotEncoder) work only on categorical columnsRobustScaler, an integer ID should not be scaled)ApplyToColsApplyToCols is a meta-transformer: it applies a transformer to columns that can be selected by name, or with filters.
Depending on the transformer, ApplyToCols either clones it and applies a copy to each column, or forwards all the columns to the same transformer.
Columns that are not selected pass through without changes.
| user_id | date | metric_1 | metric_2 | city | |
|---|---|---|---|---|---|
| 0 | 0 | 03 January 2023 | 10.3 | 3.5 | 1.0 |
| 1 | 1 | 04 February 2023 | 20.7 | 22.3 | 0.0 |
| 2 | 2 | 14 April 2023 | 30.8 | 45.1 | 2.0 |
ApplyToCols to encodeApplyToCols(OneHotEncoder(), cols=["Name", "Desc"])
ApplyToCols to decomposeApplyToCols(PCA(), cols=s.glob("metric_*"))
For example, apply the StandardScaler only to the metric_* columns, excluding the column user_id.
| user_id | date | city | metric_1 | metric_2 | |
|---|---|---|---|---|---|
| 0 | 0 | 03 January 2023 | Paris | -1.230675 | -1.183668 |
| 1 | 1 | 04 February 2023 | London | 0.011948 | -0.078389 |
| 2 | 2 | 14 April 2023 | Rome | 1.218727 | 1.262056 |
Use a scikit-learn Pipeline to concatenate multiple transformers, when wrapped in ApplyToCols:
Tip
Remember that columns that are not selected pass through without any change.
from skrub import ToDatetime, DatetimeEncoder
from sklearn.pipeline import make_pipeline
df = pd.DataFrame({
"date": ["03 January 2023", "04 February 2023"],
"city": ["Paris", "London"],
"values": [10, 20]
})
encode_datetime = make_pipeline(
ApplyToCols(ToDatetime(), cols="date"),
ApplyToCols(DatetimeEncoder(), cols="date"),
)
encode_datetime.fit_transform(df)| date_year | date_month | date_day | date_total_seconds | city | values | |
|---|---|---|---|---|---|---|
| 0 | 2023.0 | 1.0 | 3.0 | 1.672704e+09 | Paris | 10 |
| 1 | 2023.0 | 2.0 | 4.0 | 1.675469e+09 | London | 20 |
Transformers should be ordered carefully:
# Encode first, then scale
transform_1 = make_pipeline(
ApplyToCols(OneHotEncoder(sparse_output=False), cols=s.string()),
# Strings are now numbers!
ApplyToCols(StandardScaler(), cols=s.numeric())
)
# vs. Scale first, then encode
transform_2 = make_pipeline(
ApplyToCols(StandardScaler(), cols=s.numeric()),
# Strings haven't been touched
ApplyToCols(OneHotEncoder(sparse_output=False), cols=s.string())
)allow_reject ParameterWhen allow_reject=True, columns that can’t be transformed are passed through:
This is useful when you don’t know if a column may be rejected or not (e.g., you don’t know which columns are acually datetimes).
SelectCols and DropCols filter columns based on rules:
More advanced selection rules in the next chapter!
ApplyToCols: Apply a transformer to columns selected with cols, exclude with exclude_colsallow_reject: Reject columns that cannot be treatedSelectCols / DropCols: Filter columns with the cols parameter