【问题标题】:how to use ColumnTransformer() to return a dataframe?如何使用 ColumnTransformer() 返回数据框?
【发布时间】:2022-02-01 08:30:43
【问题描述】:

我有一个这样的数据框:

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() 并返回转换后的数据帧。

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

这给了我一个''类型的'稀疏矩阵'

如果我使用 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()的输出上调用.toarray(),如下pd.DataFrame(ct.fit_transform(df).toarray())。相反,对于列名,您必须坚持自定义的内容,因为OrdinalEncoder 不提供方法.get_feature_names_out(),与OneHotEncoder 不同。最后,对于转换后的列顺序,我建议查看stackoverflow.com/questions/68874492/…

标签: python-3.x dataframe scikit-learn encoder


【解决方案1】:

正如评论中快速概述的那样,您的示例需要考虑一些事项:

  • 方法.fit_transform() 通常返回一个稀疏矩阵 或一个numpy 数组。返回一个稀疏矩阵的目的是为了节省内存;考虑一下您对具有许多类别的分类属性进行一次热编码的示例。您最终将拥有一个包含许多列和每行一个非零条目的矩阵;使用稀疏矩阵,您只能存储非零元素的 location。在这种情况下,您可以在 .fit_transform() 的输出上调用 .toarray() 以获取一个 numpy 数组以传递给 pd.DataFrame 构造函数。

    实际上,在与您提供的类似的五行数据集上

    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 列作为第一列和转换后的(单热编码)部门 列从第二列到最后一列。这是因为,正如您在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

变换后的特征矩阵中的列顺序遵循变换器列表中列的指定顺序。除非在 passthrough 关键字中指定,否则未指定的原始特征矩阵的列将从生成的转换后的特征矩阵中删除。用 passthrough 指定的那些列被添加到转换器输出的右侧。

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

【讨论】:

  • 太棒了!非常感谢您抽出宝贵时间编写此详细说明。它也回答了我关于 stackoverflow 的其他问题。
猜你喜欢
  • 2016-08-07
  • 2021-07-29
  • 1970-01-01
  • 2018-11-13
  • 1970-01-01
  • 2023-01-31
  • 2019-08-10
  • 1970-01-01
相关资源
最近更新 更多