这是我的输入数据:
这是所需的输出,将转换应用于r,f和m列,并将结果附加到原始数据
代码如下:
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import PowerTransformer
df = pd.DataFrame(np.random.randint(0,100,size=(10, 3)), columns=list('rfm'))
column_trans = ColumnTransformer(
[('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']),
])
transformed = column_trans.fit_transform(df)
new_cols = ['r_std', 'f_std', 'm_std', 'r_boxcox', 'f_boxcox', 'm_boxcox']
transformed_df = pd.DataFrame(transformed, columns=new_cols)
pd.concat([df, transformed_df], axis = 1)
我还需要其他转换器,因此我需要将始发列保留在管道中。有没有更好的方法来解决这个问题?特别是在管道中进行串联和列命名吗?
答案 0 :(得分:1)
一种方法是使用虚拟转换器,该转换器仅返回转换后的列及其原始值:
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()
中显示 remainder 参数的用法,我发现它非常有用。
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 )的 remainder 可以保留未转换的列;来自docs。
使用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)
答案 1 :(得分:0)
是的,有一种方法可以做到这一点,幸运地包含在 SKLearn 中。在 ColumnTransformer 的原始文档中,您可以找到令人困惑但有用的一行,如下所示:
<块引用>transformer{‘drop’, ‘passthrough’} 或 estimator
估算器必须支持拟合和变换。也接受特殊大小写的字符串 ‘drop’ 和 ‘passthrough’,分别表示删除列或通过未转换的列。
这意味着如果您想在 ColumnTransformer
期间保留一列或在 ColumnTransformer
期间删除一列,您只需使用两个特殊大小写的字符串之一来指示它,就像这样:< /p>
column_trans = ColumnTransformer(
[('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']),
('col_keep', 'passthrough', ['r','f','m'])
])
如果您随后使用 ColumnTransformer
,那 3 列将被保留并且不会被删除。或者,如果您使用 'drop'
而不是 'passthrough'
,您可以有选择地删除某些列。这与 remainder='passthrough'
结合使用将允许您删除一些列并保留所有其他列。我希望你觉得这有用!