Один из способов сделать это - использовать фиктивный преобразователь , который просто возвращает преобразованный столбец с его исходным значением:
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import PowerTransformer
np.random.seed(1714)
class NoTransformer(BaseEstimator, TransformerMixin):
def fit(self, X, y=None):
return self
def transform(self, X):
assert isinstance(X, pd.DataFrame)
return X
Я добавляю id столбец набора данных, чтобы я мог показать использование параметра Остаток в ColumnTransformer()
, который я считаю очень полезным.
df = pd.DataFrame(np.hstack((np.arange(10).reshape((10, 1)),
np.random.randint(1,100,size=(10, 3)))),
columns=["id"] + list('rfm'))
Использование Остаток со значением passthrough (по умолчанию значение drop ) можно сохранить столбцы, которые не были преобразованы;из документов .
И используя фиктивный класс NoTransformer()
, мы можем преобразовать столбцы 'r', 'f', 'm' в одно и то же значение.
column_trans = ColumnTransformer(
[('r_original', NoTransformer(), ['r']),
('f_original', NoTransformer(), ['f']),
('m_original', NoTransformer(), ['m']),
('r_std', StandardScaler(), ['r']),
('f_std', StandardScaler(), ['f']),
('m_std', StandardScaler(), ['m']),
('r_boxcox', PowerTransformer(method='box-cox'), ['r']),
('f_boxcox', PowerTransformer(method='box-cox'), ['f']),
('m_boxcox', PowerTransformer(method='box-cox'), ['m']),
], remainder="passthrough")
Подсказка, если вы хотите преобразовать еще много столбцов: у приспособленного класса ColumnTransformer()
( column_trans в вашем случае) есть метод transformers_ , который позволяет вам получить доступ к именам['r_std', 'f_std', 'm_std', 'r_boxcox', 'f_boxcox', 'm_boxcox']
программно:
column_trans.transformers_
#[('r_original', NoTransformer(), ['r']),
# ('f_original', NoTransformer(), ['f']),
# ('m_original', NoTransformer(), ['m']),
# ('r_std', StandardScaler(copy=True, with_mean=True, with_std=True), ['r']),
# ('f_std', StandardScaler(copy=True, with_mean=True, with_std=True), ['f']),
# ('m_std', StandardScaler(copy=True, with_mean=True, with_std=True), ['m']),
# ('r_boxcox',
# PowerTransformer(copy=True, method='box-cox', standardize=True),
# ['r']),
# ('f_boxcox',
# PowerTransformer(copy=True, method='box-cox', standardize=True),
# ['f']),
# ('m_boxcox',
# PowerTransformer(copy=True, method='box-cox', standardize=True),
# ['m']),
# ('remainder', 'passthrough', [0])]
Наконец, я думаю, ваш код можно упростить следующим образом:
column_trans_2 = ColumnTransformer(
([
('original', NoTransformer(), ['r', 'f', 'm']),
('std', StandardScaler(), ['r', 'f', 'm']),
('boxcox', PowerTransformer(method='box-cox'), ['r', 'f', 'm']),
]), remainder="passthrough")
transformed_2 = column_trans_2.fit_transform(df)
column_trans_2.transformers_
#[('std',
# StandardScaler(copy=True, with_mean=True, with_std=True),
# ['r', 'f', 'm']),
# ('boxcox',
# PowerTransformer(copy=True, method='box-cox', standardize=True),
# ['r', 'f', 'm'])]
И назначить имена столбцов программно с помощью transformers_ :
new_col_names = []
for i in range(len(column_trans_2.transformers)):
new_col_names += [column_trans_2.transformers[i][0] + '_' + s for s in column_trans_2.transformers[i][2]]
# The non-transformed columns ('id' in this case) will be appended on the right of
# the array and do not show up in the 'transformers_' method.
# Add the id columns to the col_names manually
new_col_names += ['id']
# ['original_r', 'original_f', 'original_m', 'std_r', 'std_f', 'std_m', 'boxcox_r',
# 'boxcox_f', 'boxcox_m', 'id']
pd.DataFrame(transformed_2, columns=new_col_names)