I am trying to build a sklearn pipeline which does different transformations on numerical data, and different transformation on categorical data. In the process, I compare the results from ColumnTransformer vs FeatureUnion, and they are not the same. Please advise if the following are equivalent, if not what the problem is. The data is from kaggle https://www.kaggle.com/ronitf/heart-disease-uci

from sklearn.model_selection import train_test_split
cat_attribs = ['sex','cp','fbs','restecg','exang','ca','thal']
num_attribs = ['trestbps','chol','thalach','oldpeak','slope']
X_train,X_test,y_train,y_test = train_test_split(heart_df,y,test_size=0.25,random_state=100)

Approach #1, using column transformer

from sklearn.compose import ColumnTransformer
ct = ColumnTransformer([('oneHot', OneHotEncoder(categories='auto'),cat_attribs)
                       , ('minMax',MinMaxScaler(),num_attribs)])
ct_result = ct.fit_transform(X_train)

Approach #2, using FeatureUnion

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import FeatureUnion
from sklearn.pipeline import Pipeline
class DataFrameSelector(BaseEstimator, TransformerMixin):
    def __init__(self, attribute_names):
        self.attribute_names = attribute_names
    def fit(self, X, y=None):
        return self
    def transform(self, X):
        return X[self.attribute_names].values

num_pipeline = Pipeline([('selector', DataFrameSelector(num_attribs)),
cat_pipeline = Pipeline([('selector', DataFrameSelector(cat_attribs)),
full_pipeline = FeatureUnion(transformer_list=[
    ('num_pipeline', num_pipeline),
    ('cat_pipeline', cat_pipeline)])
fp_result= full_pipeline.fit_transform(X_train)

I've tried this with an sklearn builtin dataset rather than yours, but the only difference appears to be the order of the columns. Switching the order of the elements in the transformer lists produces the same results. (In both cases, the numeric columns and categorical one-hot encoded columns are separated from each other, but are placed in the order that they appear in the transformer list.)

  • $\begingroup$ It was the order of columns: My #1 had cat_attribs followed by num_attribs. And #2 had the other way round. So switching them gave me True for np.all(ct_result == fp_result). Thanks! $\endgroup$ – user61034 May 14 '19 at 2:10

Both of these methods are used to combine independent transformations (transformers) into a single transformer, by independent I mean transformation (transformers) that don't need to be executed in a defined order. That's because unlike in regular pipelines, one transformer is not applied to the output of another transformer.

The main difference is that: each transformer in a feature union object gets the whole data as input. While in column transformer object they get only part of the data as input. Both of them concatenate the results of each transformer in the end. Both can use parallel processing.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.