【问题标题】:Scikit-learn Column Transformer does not return back feature namesScikit-learn Column Transformer 不返回特征名称
【发布时间】:2021-11-02 19:33:22
【问题描述】:

我正在尝试使用带有 OneHotEncoder 的 Column Transformer 来转换我的分类数据:

快速查看我的数据:

我想对 3 个特征进行一次热编码:'sex'、'smoker'、'region',所以我使用 scikit-learn 的 Column Transformer。 (我不想分开数字和分类,而不是单独转换它们,我只想在单个数据集上执行它们)

我的代码:


cat_feature = X.select_dtypes(include = 'object') #select only categorical columns 

enc = ColumnTransformer([ ('one_hot_encoder' , OneHotEncoder() , cat_feature ) ] , 
                     remainder = 'passthrough')

X_transformed  =  enc.fit_transform(X)   # transformed version of original data


我的问题是,X_transformed 被删除了所有功能名称,这对我来说有点令人困惑:

那么在进行此转换后,无论如何要保留我的列名吗?我想将此转换器合并到管道中,因此我不能使用pd.get_dummies。 谢谢!!

【问题讨论】:

  • 来自此链接:scikit-learn.org/stable/modules/generated/…。 ColumnTransformer 的返回是 list,您需要额外的库来解决您的问题。为什么你不能使用pandas?
  • @user1740577 因为我想把它做成一个完整的管道,所以我不能使用pd.get_dummies
  • 你看到我发的链接了吗?
  • 是的,我看到了,但从我读过的内容来看,对我来说唯一有用的是get_feature_names,但它只返回分类列的名称,它没有指定名称是什么在我的情况下,X_transformed 的第 1 列。这就是为什么我真的想使用 pd.get_dummies 但这个不允许我将它放入 scikit-learn 管道中。
  • 请详细说明get_feature_names不够用的原因。它应该为所有列提供名称。

标签: python pandas machine-learning scikit-learn one-hot-encoding


【解决方案1】:

我举个例子,希望对你有帮助: (为了回答你的问题,我使用来自OneHotEncoder 的get_feature_names)

import pandas as pd
from sklearn.preprocessing import OneHotEncoder


d = {
    'Sex': ['female', 'male', 'male'],
    'BMI': [27 , 33 , 31 ],
    'REG': ['south', 'west', 'south']
}

X = pd.DataFrame(d)
print(X)

cat_feature = X.select_dtypes(include = 'object') #select only categorical columns 

enc = OneHotEncoder(handle_unknown='ignore')

X_transformed = enc.fit_transform(cat_feature).toarray().tolist()

X_transformed = pd.DataFrame(X_transformed)

X_transformed.columns = enc.get_feature_names()
      Sex  BMI    REG
0  female   27  south
1    male   33   west
2    male   31  south

【讨论】:

  • 天哪,这才是我真正的意思!终于知道答案了,谢谢你哦
  • @Miku 欢迎,我很高兴能帮助你。如果这是正确的,请阅读此链接:meta.stackexchange.com/questions/5234/…
  • @Miku 非常感谢 WOMAN 如果您同意并且这正是您想要的,请编辑您的问题的标题并在标题中添加此文本 (get_feature_names from OneHotEncoder) 功能用户可以找到此 Q&A
  • 这会忽略连续的列。但是ColumnTransformer 也有一个get_feature_names 方法,它部分调用了Onehotencoder.get_feature_names。
  • 我重新阅读了这个问题,但我仍然认为这没有抓住重点。有问题的数据具有应该传递的三个非分类特征,但此答案未解决这些特征。 OP 没有转向ColumnTransformer,因为OneHotEncoder.get_feature_names 失败,而是因为应该保留剩余的功能。我将“我不想将数字一个和分类一个分开......”这句话解释为 OP 希望避免手动拆分和合并数据,而这正是 ColumnTransformer 的用途。
【解决方案2】:

使用必须编写自定义的Transformer,它会传递并支持get_feature_names

步骤:

  1. 自定义Transformer,它将通过get_feature_names返回通过列名
  2. 不要使用 remainder = 'passthrough',而是使用我们自定义的Transformer

使用enc.get_feature_names()获取功能列表。

示例:

from sklearn.base import BaseEstimator

df = pd.DataFrame({
    'age': [1,2,3,4],
    'sex': ['male', 'female']*2,
    'bmi': [1.1,2.2,3.3,4.4],
    'children': [1]*4,
    'smoker': ['yes', 'no']*2
})
cat_features = df.select_dtypes(include = 'object').columns
passthrough_features = [c for c in df.columns if c not in cat_features]

class PassthroughTransformer(BaseEstimator):
  def fit(self, X, y = None):
    self.cols = X.columns
    return self

  def transform(self, X, y = None):
    self.cols = X.columns
    return X.values

  def get_feature_names(self):
    return self.cols

enc = ColumnTransformer([ ('1hot' , OneHotEncoder() , cat_features ),
                         ('pass' , PassthroughTransformer(), passthrough_features)])
X_transformed   = enc.fit_transform(df)
pd.DataFrame(X_transformed, columns=enc.get_feature_names())

输出:

    1hot__x0_female 1hot__x0_male   1hot__x1_no 1hot__x1_yes    pass__age   pass__bmi   pass__children
0   0.0             1.0             0.0         1.0             1.0         1.1         1.0
1   1.0             0.0             1.0         0.0             2.0         2.2         1.0
2   0.0             1.0             0.0         1.0             3.0         3.3         1.0
3    1.0            0.0             1.0         0.0             4.0         4.4         1.0

【讨论】:

  • 哦,我会记住的,你的回答对我很有用:D。这绝对会救我!!
  • ColumnTransformer.get_feature_names 已经可以使用直通余数,因此不需要自定义转换器。
猜你喜欢
  • 2019-10-20
  • 2022-11-28
  • 2016-02-25
  • 2018-02-24
  • 1970-01-01
  • 2016-06-23
  • 2016-08-20
  • 2018-09-23
  • 2013-03-07
相关资源
最近更新 更多