如何使用 ColumnTransformer() 到 return 数据框?

how to use ColumnTransformer() to return a dataframe?

我有这样一个数据框:

department      review  projects salary satisfaction bonus  avg_hrs_month   left
0   operations  0.577569    3   low         0.626759    0   180.866070      0
1   operations  0.751900    3   medium      0.443679    0   182.708149      0
2   support     0.722548    3   medium      0.446823    0   184.416084      0
3   logistics   0.675158    4   high        0.440139    0   188.707545      0
4   sales       0.676203    3   high        0.577607    1   179.821083      0

我想尝试 ColumnTransformer() 和 return 转换后的数据框。

ord_features = ["salary"]
ordinal_transformer = OrdinalEncoder()


cat_features = ["department"]
categorical_transformer = OneHotEncoder(handle_unknown="ignore")

ct = ColumnTransformer(
    transformers=[
        ("ord", ordinal_transformer, ord_features),
        ("cat", categorical_transformer, cat_features ),
           ]
)

df_new = ct.fit_transform(df)
df_new

这给了我 'sparse matrix of type ''

如果我使用 pd.DataFrame(ct.fit_transform(df)) 那么我将得到一个列:

                            0
0   (0, 0)\t1.0\n (0, 7)\t1.0
1   (0, 0)\t2.0\n (0, 7)\t1.0
2   (0, 0)\t2.0\n (0, 10)\t1.0
3   (0, 5)\t1.0
4   (0, 9)\t1.0

然而,我期待看到这样转换后的数据框?

    review  projects salary satisfaction bonus  avg_hrs_month   operations support ...
0   0.577569    3    1      0.626759     0      180.866070      1           0
1   0.751900    3    2      0.443679     0      182.708149      1           0  
2   0.722548    3    2      0.446823     0      184.416084      0           1
3   0.675158    4    3      0.440139     0      188.707545      0           0
4   0.676203    3    3      0.577607     1      179.821083      0           0

是否可以使用 ColumnTransformer()?

正如评论中快速勾勒的那样,在您的示例中有几个注意事项需要完成:

  • 方法.fit_transform()通常returns要么是稀疏矩阵要么是numpy数组 .返回一个稀疏矩阵是为了节省内存;想一想您 one-hot-encode 具有许多类别的分类属性的示例。您最终会得到一个包含许多列和每行一个 non-zero 条目的矩阵;使用稀疏矩阵,您只能存储 non-zero 元素的 location。在这些情况下,您可以在 .fit_transform() 的输出上调用 .toarray() 以获取返回的 numpy 数组以传递给 pd.DataFrame 构造函数。

    实际上,five-rows 数据集类似于您提供的数据集

    df = pd.DataFrame({
        'department': ['operations', 'operations', 'support', 'logistics', 'sales'],
        'review': [0.577569, 0.751900, 0.722548, 0.675158, 0.676203],
        'projects': [3, 3, 3, 4, 3],
        'salary': ['low', 'medium', 'medium', 'low', 'high'],
        'satisfaction': [0.626759, 0.751900, 0.722548, 0.675158, 0.676203],
        'bonus': [0, 0, 0, 0, 1],
        'avg_hrs_month': [180.866070, 182.708149, 184.416084, 188.707545, 179.821083],
        'left': [0, 0, 1, 0, 0]
    })
    
    ord_features = ["salary"]
    ordinal_transformer = OrdinalEncoder()
    
    cat_features = ["department"]
    categorical_transformer = OneHotEncoder(handle_unknown="ignore")
    
    ct = ColumnTransformer(transformers=[
        ("ord", ordinal_transformer, ord_features),
        ("cat", categorical_transformer, cat_features),
    ])
    

    我无法重现你的问题(即,我直接获得了一个 numpy 数组),但基本上 pd.DataFrame(ct.fit_transform(df).toarray()) 应该适用于你的情况。这是您将获得的输出:

  • 如您所见,关于您的预期输出,这仅包含转换后(按顺序编码)的 salary 列作为第一列和转换后的 ( one-hot-encoded) 部门 列从第二列到最后一列。这是因为,正如您在 docs 中看到的那样,参数 remainder 默认设置为 'drop',这意味着所有不受转换影响的列都将被删除。为避免这种情况,您应该将其设置为 'passthrough';这将帮助您转换所需的列并保持其他列不变。

    ct = ColumnTransformer(transformers=[
        ("ord", ordinal_transformer, ord_features),
        ("cat", categorical_transformer, cat_features )],
        remainder='passthrough'
    )
    

    在这种情况下,这将是您的 pd.DataFrame(ct.fit_transform(df).toarray()) 的输出:

  • 同样,如您所见,列顺序在转换后并不是您所期望的那样。长话短说,那是因为 ColumnTransformer

The order of the columns in the transformed feature matrix follows the order of how the columns are specified in the transformers list. Columns of the original feature matrix that are not specified are dropped from the resulting transformed feature matrix, unless specified in the passthrough keyword. Those columns specified with passthrough are added at the right to the output of the transformers.

我建议阅读 Preserve column order after applying sklearn.compose.ColumnTransformer 这个提议。

  • 最终,对于与列名称有关的问题,您可能应该应用自定义解决方案,将您想要的内容直接传递给 columns 参数,然后再传递给 pd.DataFrame 构造函数。实际上,OrdinalEncoder(与 OneHotEncoder 不同)没有提供 .get_feature_names_out() 方法,使得通常可以轻松地将 columns=ct.get_feature_names_out() 传递给 pd.DataFrame 构造函数。有关其用法的示例,请参阅