【问题标题】:Apply StandardScaler to parts of a data set将 StandardScaler 应用于部分数据集
【发布时间】:2016-11-20 02:58:48
【问题描述】:

我想使用sklearnStandardScaler。是否可以将其应用于某些特征列但不能应用于其他列?

例如,假设我的data 是:

data = pd.DataFrame({'Name' : [3, 4,6], 'Age' : [18, 92,98], 'Weight' : [68, 59,49]})

   Age  Name  Weight
0   18     3      68
1   92     4      59
2   98     6      49


col_names = ['Name', 'Age', 'Weight']
features = data[col_names]

我适应并改造了data

scaler = StandardScaler().fit(features.values)
features = scaler.transform(features.values)
scaled_features = pd.DataFrame(features, columns = col_names)

       Name       Age    Weight
0 -1.069045 -1.411004  1.202703
1 -0.267261  0.623041  0.042954
2  1.336306  0.787964 -1.245657

当然,名称不是真正的整数而是字符串,我不想将它们标准化。如何仅在 AgeWeight 列上应用 fittransform 方法?

【问题讨论】:

    标签: python pandas scikit-learn scale data-science


    【解决方案1】:

    v0.20 中引入了 ColumnTransformer,它将转换器应用于数组或 pandas DataFrame 的一组指定列。

    import pandas as pd
    data = pd.DataFrame({'Name' : [3, 4,6], 'Age' : [18, 92,98], 'Weight' : [68, 59,49]})
    
    col_names = ['Name', 'Age', 'Weight']
    features = data[col_names]
    
    from sklearn.compose import ColumnTransformer
    from sklearn.preprocessing import StandardScaler
    
    ct = ColumnTransformer([
            ('somename', StandardScaler(), ['Age', 'Weight'])
        ], remainder='passthrough')
    
    ct.fit_transform(features)
    

    注意:与 Pipeline 一样,它也有一个速记版本 make_column_transformer,不需要命名转换器

    输出

    -1.41100443,  1.20270298,  3.       
     0.62304092,  0.04295368,  4.       
     0.78796352, -1.24565666,  6.       
    

    【讨论】:

    • 这是现在最好的答案(不需要你复制数据框)
    • 不错的答案!如果我使用 pandas 数据框执行此操作,如何保留列名?有没有办法不用在最后重命名所有列?
    • 这是我一直在寻找的最佳答案,而且速度更快,尽管使用 apply 也是一种替代方法。
    【解决方案2】:

    更新:

    目前处理此问题的最佳方法是使用 ColumnTransformer,如 here 所述。


    首先创建数据框的副本:

    scaled_features = data.copy()
    

    不要在转换中包含名称列:

    col_names = ['Age', 'Weight']
    features = scaled_features[col_names]
    scaler = StandardScaler().fit(features.values)
    features = scaler.transform(features.values)
    

    现在,不要创建新数据框,而是将结果分配给这两列:

    scaled_features[col_names] = features
    print(scaled_features)
    
    
            Age  Name    Weight
    0 -1.411004     3  1.202703
    1  0.623041     4  0.042954
    2  0.787964     6 -1.245657
    

    【讨论】:

    • 它可以工作,但我无法使用“inverse_transform”函数通过此方法获取初始值。 'test = scaled_features.iloc[1,:]' 'test_inverse = scaler.inverse_transform(test)' 我得到了错误:ValueError: 操作数不能与形状一起广播 (3,) (2,) (3,)
    • scaler.inverse_transform(scaled_features[col_names].values) 为我工作。
    • 我试图用第一行测试inverse_transform 函数。是的,它也适用于我,但我失去了names 专栏。如果我(重新)转换所有数据框,我可以插入它。但是如果我只想inverse_transform 第一行呢?
    • 对不起,如果我不清楚,但是当我提到列 name 时,我设计了包含名称的列(数据框的第二列,我不想缩放的列) 不是列的名称
    • 是(不一定是第一行,而是结构相同的新行)
    【解决方案3】:

    聚会迟到了,但这是我的首选解决方案:

    #load data
    data = pd.DataFrame({'Name' : [3, 4,6], 'Age' : [18, 92,98], 'Weight' : [68, 59,49]})
    
    #list for cols to scale
    cols_to_scale = ['Age','Weight']
    
    #create and fit scaler
    scaler = StandardScaler()
    scaler.fit(data[cols_to_scale])
    
    #scale selected data
    data[cols_to_scale] = scaler.transform(data[cols_to_scale])
    

    【讨论】:

      【解决方案4】:

      另一种选择是在缩放之前删除名称列,然后将其重新合并在一起:

      data = pd.DataFrame({'Name' : [3, 4,6], 'Age' : [18, 92,98], 'Weight' : [68, 59,49]})
      from sklearn.preprocessing import StandardScaler
      
      # Save the variable you don't want to scale
      name_var = data['Name']
      
      # Fit scaler to your data
      scaler.fit(data.drop('Name', axis = 1))
      
      # Calculate scaled values and store them in a separate object
      scaled_values = scaler.transform(data.drop('Name', axis = 1))
      
      data = pd.DataFrame(scaled_values, index = data.index, columns = data.drop('ID', axis = 1).columns)
      data['Name'] = name_var
      
      print(data)
      

      【讨论】:

        【解决方案5】:

        我找到的最简单的方法是:

        from sklearn.preprocessing import StandardScaler
        # I'm selecting only numericals to scale
        numerical = temp.select_dtypes(include='float64').columns
        # This will transform the selected columns and merge to the original data frame
        temp.loc[:,numerical] = StandardScaler().fit_transform(temp.loc[:,numerical])
        

        输出

                 Age  Name    Weight
        0 -1.411004     3  1.202703
        1  0.623041     4  0.042954
        2  0.787964     6 -1.245657
        

        【讨论】:

          【解决方案6】:

          一种更 Pythonic 的方式来做到这一点 -

          from sklearn.preprocessing import StandardScaler
          data[['Age','Weight']] = data[['Age','Weight']].apply(
                                     lambda x: StandardScaler().fit_transform(x))
          data 
          

          输出 -

                   Age  Name    Weight
          0 -1.411004     3  1.202703
          1  0.623041     4  0.042954
          2  0.787964     6 -1.245657
          

          【讨论】:

          • “我怎样才能只在年龄和体重列上应用拟合和变换函数”。我不知道 OP 想要做这些事情。
          猜你喜欢
          • 2019-04-08
          • 2011-02-18
          • 2019-08-31
          • 1970-01-01
          • 2019-08-11
          • 2014-10-10
          • 2021-09-09
          • 2021-12-17
          相关资源
          最近更新 更多