【问题标题】:Using sklearn StandardScaler on only select columns [duplicate]仅在选择列上使用 sklearn StandardScaler
【发布时间】:2018-08-23 06:52:22
【问题描述】:

我有一个 numpy 数组 X,它有 3 列,如下所示:

array([[    3791,     2629,        0],
       [ 1198760,   113989,        0],
       [ 4120665,        0,        1],
       ...

前 2 列是连续值,最后一列是二进制 (0,1)。我想仅将 StandardScaler 类应用于前 2 列。我目前正在通过以下方式执行此操作:

scaler = StandardScaler()
X_subset = scaler.fit_transform(X[:,[0,1]])
X_last_column = X[:, 2]
X_std = np.concatenate((X_subset, X_last_column[:, np.newaxis]), axis=1)

那么 X_std 的输出是:

array([[-0.34141308, -0.18316715,  0.        ],
       [-0.22171671, -0.17606473,  0.        ],
       [ 0.07096154, -0.18333483,  1.        ],
       ...,

有没有办法一步完成这一切?我想将此作为管道的一部分包含在内,它将缩放前 2 列并保留最后一个二进制列。

【问题讨论】:

    标签: python dataset scikit-learn


    【解决方案1】:

    从 scikit-learn 0.20 版开始,您可以将函数 sklearn.compose.ColumnTransformer 完全用于此目的。

    【讨论】:

      【解决方案2】:

      感谢您的回复。我最终使用一个类来选择这样的列:

      class ItemSelector(BaseEstimator, TransformerMixin):
      
          def __init__(self, columns):
              self.columns = columns
      
          def fit(self, x, y=None):
              return self
      
          def transform(self, data_array):
              return data_array[:, self.columns]
      

      然后我在我的管道中使用 FeatureUnion 来将 StandardScaler 仅适用于连续变量:

      FeatureUnion(
          transformer_list=[
              ('continous', Pipeline([  # Scale the first 2 numeric columns
                  ('selector', ItemSelector(columns=[0, 1])),
                  ('scaler', StandardScaler())
              ])),
              ('categorical', Pipeline([  # Leave the last binary column as is
                  ('selector', ItemSelector(columns=[2]))
              ]))
          ]
      )
      

      这对我很有效。

      【讨论】:

        【解决方案3】:

        受 skd 建议扩展 StandardScaler 的启发,我提出了以下建议。它不是超级高效或健壮(例如,您需要更新 inverse_transform 函数),但希望这是一个有用的起点:

        class StandardScalerSelect(StandardScaler):
        
            def __init__(self, copy=True, with_mean=True, with_std=True, cols=None):
                self.cols = cols
                super().__init__(copy, with_mean, with_std)
        
            def transform(self, X):
        
                not_transformed_ix = np.isin(np.array(X.columns), np.array(self.cols), invert=True)
        
                # Still transforms all, just for convenience. For larger datasets
                # will want to modify self.mean_ and self.scale_ so the dimensions match,
                # and then just transform the subset
                trans = super().transform(X)
        
                trans[:,not_transformed_ix] = np.array(X.iloc[:,not_transformed_ix])
        
                return trans 
        

        【讨论】:

          【解决方案4】:

          我想不出另一种方法来压缩你的代码,但你绝对可以在管道中使用你的转换。您必须定义一个扩展 StandardScaler 的类,它只对作为参数传递的列执行转换,保持其他列不变。请参阅example 中的代码,您必须编写类似于 ItemSelector 的程序。

          【讨论】:

          • 谢谢。您链接的 ItemSelector 类和 FeatureUnion 是我将其放入管道所需要的。
          猜你喜欢
          • 1970-01-01
          • 2022-01-12
          • 2019-02-17
          • 2020-07-16
          • 2018-03-15
          • 2022-08-08
          • 2016-08-25
          • 2021-05-11
          • 2018-08-21
          相关资源
          最近更新 更多