python - 为什么 ColumnTransformer 中的 SimpleImputer 会创建额外的列?

标签 python scikit-learn

我正在关注 Aurelion Geron 的机器学习书籍。

我正在试验 ColumnTransformer 类。当我包含 SimplerImputer 时,会创建一个额外的列。我知道 SimplerImputer 用于填充 total_bedrooms 列(结果中的列索引 4)中的缺失值,因此我不清楚它为什么要添加新列(列索引: 10) 结果。

当我不包括 ColumnTransformer 中的 SimplerImputer,但是创建一个实例,fit_transform ColumnTransformer 的输出,我不会得到附加列。请指教。

category_att = X.select_dtypes(include='object').columns
num_att = X.select_dtypes(include='number').columns

transformer = ColumnTransformer(
    [
    ('adder', AttributeAdder(), num_att ),
    ('imputer', SimpleImputer(strategy='median'), ['total_bedrooms']),
    ('ohe', OneHotEncoder(), category_att)
    ],
    remainder = 'passthrough'
)

用于添加两个新功能/列的自定义类

class AttributeAdder(BaseEstimator, TransformerMixin):
    
    def __init__(self, add_bed_room = False):
        self.add_bed_room = add_bed_room
    
    def fit(self,y=None):
        return self
    
    def transform(self,X,y=None):
        
        room_per_household = X.iloc[: , t_room ] / X.iloc[: , t_household ]
        population_per_household = X.iloc[: , t_population ] / X.iloc[: , t_household ]
        return np.c_[X,room_per_household,population_per_household]

结果 enter image description here

最佳答案

为什么

它不完全是 SimpleImputer;它是 ColumnTransformer 本身。 ColumnTransformer 并行应用其更改器(mutator),而不是顺序应用(另请参阅 [1][2] ),因此如果一个列被传递给多个更改器(mutator),您最终会在输出。在你的例子中,输出第 4 列来自 total_bedrooms 上的 "adder"(它什么也没做,所以仍然有缺失值),输出第 10 列来自 "imputer"(因此不会有缺失值)。

修复

在这种特殊情况下,两种方法似乎是最简单的。

归因于一切

任何没有缺失的数字特征都不会受到影响。但是,如果您希望管道在包含缺失值的 future 数据上出错,则不要这样做。

num_pipe = Pipeline([
    ("add_feat", AttributeAdder()),
    ("impute", SimpleImputer(strategy="median")),
])
transformer = ColumnTransformer(
    [
        ('num', num_pipe, num_att),
        ('cat', OneHotEncoder(), category_att),
    ],
    remainder = 'passthrough',
)

较小的变压器柱组

因为您的 AttributeAdder 实际上不需要您的 total_bedrooms 列,所以您不需要将它传递到该转换器中。具体细节取决于您如何使用 t_roomst_households 等,但通常:

transformer = ColumnTransformer(
    [
        ('adder', AttributeAdder(), [["total_rooms", "households", "population"]]),
        ('imputer', SimpleImputer(strategy='median'), ['total_bedrooms']),
        ('ohe', OneHotEncoder(), category_att)
    ],
    remainder = 'passthrough'  # now you're relying on this one much more
)

在相关方法中,您可以更灵活地计算添加的特征。更改您的 AttributeAdder 以返回新功能(不要在 transform 的最后一步连接到 X ),并依靠 ColumnTransformer 来传递这些功能。 (请注意,我们不能依赖于 remainder,但我们可以使用 “passthrough” 作为转换器之一。)

class AttributeAdder(BaseEstimator, TransformerMixin):
    ...
    def transform(self,X,y=None):
        ...
        return np.c_[room_per_household,population_per_household]


transformer = ColumnTransformer(
    [
        ('adder', AttributeAdder(), num_att),
        ('num', "passthrough", num_att.drop(['total_bedrooms'])),
        ('imputer', SimpleImputer(strategy='median'), ['total_bedrooms']),
        ('ohe', OneHotEncoder(), category_att)
    ],
    passthrough=True,  # if you have columns in neither of num_att and category_att that you want kept
)

关于python - 为什么 ColumnTransformer 中的 SimpleImputer 会创建额外的列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67250392/

相关文章:

python - SelectKBest (chi2) 如何计算分数?

python - 比较谷歌应用程序引擎数据存储中的多个日期范围(多对多,Python)

python - 努力学习 python 的基本部分(检查变量是否等于输入)

python - 使用支持向量回归进行时间序列预测

python - 属性错误: 'numpy.ndarray' object has no attribute 'lower' fitting logistic model data

python - 如何在 Scikit-Learn 中绘制超过 10 倍交叉验证的 PR 曲线

python - 带有索引的 Scikit-learn train_test_split

python - 为什么 `requests`要用 `with`语句呢?

python - 如何将经过身份验证的用户设置为序列化器?

python - 如何检查一个程序/目录/文件是否被经常使用? (在 Windows 中)