【问题标题】:How to retain column headers of data frame after Pre-processing in scikit-learn如何在 scikit-learn 中进行预处理后保留数据帧的列标题
【发布时间】:2015-06-17 15:24:15
【问题描述】:

我有一个熊猫数据框,其中包含一些行和列。每列都有一个标题。现在只要我继续在 pandas 中进行数据操作操作,我的变量标头就会被保留。但是,如果我尝试使用 Sci-kit-learn lib 的一些数据预处理功能,我最终会丢失所有标题,并且帧会被转换为数字矩阵。

我理解为什么会发生这种情况,因为 scikit-learn 提供了一个 numpy ndarray 作为输出。并且 numpy ndarray 只是矩阵不会有列名。

但事情就是这样。如果我在我的数据集上构建一些模型,即使在初始数据预处理并尝试了一些模型之后,我可能还需要做更多的数据操作任务来运行一些其他模型以获得更好的拟合。由于无法访问列标题,因此很难进行数据操作,因为我可能不知道特定变量的索引是什么,但是通过执行 df.columns 更容易记住变量名甚至查找。

如何克服呢?

EDIT1:使用示例数据快照进行编辑。

    Pclass  Sex Age SibSp   Parch   Fare    Embarked
0   3   0   22  1   0   7.2500  1
1   1   1   38  1   0   71.2833 2
2   3   1   26  0   0   7.9250  1
3   1   1   35  1   0   53.1000 1
4   3   0   35  0   0   8.0500  1
5   3   0   NaN 0   0   8.4583  3
6   1   0   54  0   0   51.8625 1
7   3   0   2   3   1   21.0750 1
8   3   1   27  0   2   11.1333 1
9   2   1   14  1   0   30.0708 2
10  3   1   4   1   1   16.7000 1
11  1   1   58  0   0   26.5500 1
12  3   0   20  0   0   8.0500  1
13  3   0   39  1   5   31.2750 1
14  3   1   14  0   0   7.8542  1
15  2   1   55  0   0   16.0000 1

以上基本就是pandas数据框了。现在,当我在此数据框上执行此操作时,它将去除列标题。

from sklearn import preprocessing 
X_imputed=preprocessing.Imputer().fit_transform(X_train) 
X_imputed

新数据是 numpy 数组,因此列名被剥离。

array([[  3.        ,   0.        ,  22.        , ...,   0.        ,
          7.25      ,   1.        ],
       [  1.        ,   1.        ,  38.        , ...,   0.        ,
         71.2833    ,   2.        ],
       [  3.        ,   1.        ,  26.        , ...,   0.        ,
          7.925     ,   1.        ],
       ..., 
       [  3.        ,   1.        ,  29.69911765, ...,   2.        ,
         23.45      ,   1.        ],
       [  1.        ,   0.        ,  26.        , ...,   0.        ,
         30.        ,   2.        ],
       [  3.        ,   0.        ,  32.        , ...,   0.        ,
          7.75      ,   3.        ]])

因此,当我对我的 pandas 数据框进行一些数据操作时,我想保留列名。

【问题讨论】:

  • 熊猫代码示例可能更有用。 Pandas 不是提供了一种从帧中提取数据,然后用新副本替换它的方法吗?
  • @Manish :请提供一个非常简单、可重现的示例!三行数据框将使您的问题更容易理解。 (也许只是复制 saved_cols = df.columns 然后将其重新分配给修改后的 df 就可以了,但我不确定这是否是您所需要的)
  • 确实,正如@cd98 所说,复制saved_cols = df.columns,然后当您获得系列时,执行pandas.DataFrame(series, saved_cols),您将获得您的数据框。例如,我在使用train_test_split 时会这样做,它会返回一个numpy ndarray,但我需要将它用作数据框。这不是什么值得特别自豪的事情,但在我看来已经足够了。
  • @lrnzcig 那是哪个版本?我认为这适用于 0.16 的 train_test_split。
  • @AndreasMueller 确实我已经升级到 0.16 并且无需再为 train_test_split 执行此操作。谢谢。

标签: python numpy pandas scikit-learn


【解决方案1】:

scikit-learn 在大多数情况下确实会去除列标题,因此只需在之后重新添加它们即可。在您的示例中,X_imputed 作为 sklearn.preprocessing 输出,X_train 作为原始数据框,您可以使用以下命令重新打开列标题:

X_imputed_df = pd.DataFrame(X_imputed, columns = X_train.columns)

【讨论】:

  • 非常感谢你的回答......我被困在同一个问题上,你的回答解决了我的问题。
  • 如果我的预处理步骤是特征销售怎么办?说,我有 1000 列,经过预处理 (sklearn.feature_selection.SelectPercentile) 它只返回 100 列。我怎么知道哪些列被删除了哪些没有被删除
  • @SupreethMeka 你有想过这个吗?
  • 使用get_support methodX_selected_df = pd.DataFrame(X_selected, columns=[X_train.columns[i] for i in range(len(X_train.columns)) if feature_selector.get_support()[i]])
  • 也可以添加索引。 pd.DataFrame(data = transformed_data), columns = train_data.columns, index = train_data.index
【解决方案2】:

根据Ami Tavory's 回复here,根据文档,Imputer 会省略空列或行(无论您如何运行它)。
因此,在运行 Imputer 并按照above 的描述设置列名之前,运行如下内容(对于列):

X_train=X_train.dropna(axis=1, how='all')

df.dropna described here.

【讨论】:

  • 我认为您的建议是在predict 阶段也这样做。如果在predict 这些列不为空,这将导致错误
  • 最好使用这个:selected_cols[~pd.isnull(self.model_.steps[0][1].statistics_)]
【解决方案3】:

改编自 Kaggle 中级机器学习课程的一部分:

from sklearn.impute import SimpleImputer

# Imputation
my_imputer = SimpleImputer()
imputed_X = pd.DataFrame(my_imputer.fit_transform(X))

# Imputation removed column names; put them back
imputed_X.columns = X.columns

【讨论】:

  • 这个答案不完整,并没有解决问题。
【解决方案4】:

以上答案仍然没有解决主要问题。这里有两个隐含的假设

  1. 数据集的所有特征都将被保留,这可能不是真的。例如。某种特征选择功能。
  2. 所有特征都将以相同的顺序保留,同样在某些特征选择转换中可能存在隐式排序。

至少在某些 fit 和 transform 函数中有一个“get_support()”方法,用于保存有关保留哪些列(特征)以及保留顺序的信息。

您可以在此处查看该功能的基础知识以及如何使用它... Find get_support() function description here

这将是获取此处所需信息的最首选和官方方式。

【讨论】:

    【解决方案5】:

    scikit-learn 有一个 get_feature_names() 方法。这个想法是从here借来的。

    from sklearn import preprocessing as pp
    
    poly = pp.PolynomialFeatures(3, interaction_only=False, include_bias=False)
    
    poly.fit(X_train)
    
    X_test_new=pd.DataFrame(poly.transform(X_test), columns=poly.get_feature_names(X_test.columns))
    X_test_new.head()
    

    【讨论】:

      猜你喜欢
      • 2016-08-12
      • 2018-11-22
      • 2018-07-07
      • 2021-05-28
      • 1970-01-01
      • 2021-10-08
      • 2017-03-10
      • 2019-03-29
      • 2022-07-19
      相关资源
      最近更新 更多