如何使用pleas sklearn fit_transform并返回数据帧而不是numpy数组?

时间:2016-03-01 12:51:47

标签: python numpy pandas scikit-learn

我想将扩展(使用sklearn.preprocessing中的StandardScaler())应用到pandas数据帧。以下代码返回一个numpy数组,因此我丢失了所有列名和indeces。这不是我想要的。

features = df[["col1", "col2", "col3", "col4"]]
autoscaler = StandardScaler()
features = autoscaler.fit_transform(features)

A"解决方案"我在网上找到的是:

features = features.apply(lambda x: autoscaler.fit_transform(x))

它似乎有效,但会导致弃用警告:

  

/usr/lib/python3.5/site-packages/sklearn/preprocessing/data.py:583:   弃用警告:传递1d数组作为数据在0.17中弃用   并将在0.19中引发ValueError。使用重塑您的数据   X.reshape(-1,1)如果您的数据有单个特征或X.reshape(1,-1)   如果它包含单个样本。

我因此尝试过:

features = features.apply(lambda x: autoscaler.fit_transform(x.reshape(-1, 1)))

但是这给了:

  

回溯(最近一次呼叫最后一次):文件" ./ analyse.py",第91行,          features = features.apply(lambda x:autoscaler.fit_transform(x.reshape(-1,1)))文件   " /usr/lib/python3.5/site-packages/pandas/core/frame.py" ;,第3972行,在   应用       return self._apply_standard(f,axis,reduce = reduce)File" /usr/lib/python3.5/site-packages/pandas/core/frame.py" ;, line 4081,in   _apply_standard       result = self._constructor(data = results,index = index)File" /usr/lib/python3.5/site-packages/pandas/core/frame.py" ;,第226行,in   的初始化       mgr = self._init_dict(data,index,columns,dtype = dtype)File" /usr/lib/python3.5/site-packages/pandas/core/frame.py" ;,第363行,in   _init_dict       dtype = dtype)文件" /usr/lib/python3.5/site-packages/pandas/core/frame.py" ;,第5163行,在   _arrays_to_mgr       arrays = _homogenize(arrays,index,dtype)File" /usr/lib/python3.5/site-packages/pandas/core/frame.py" ;, line 5477,in   _homogenize       raise_cast_failure = False)File" /usr/lib/python3.5/site-packages/pandas/core/series.py" ;,第2885行,   在_sanitize_array中       提高异常('数据必须是1维')例外:数据必须是1维的

如何将缩放应用于pandas数据帧,使数据帧保持不变?如果可能的话,不要复制数据。

8 个答案:

答案 0 :(得分:40)

您可以使用as_matrix()将DataFrame转换为numpy数组。随机数据集上的示例:

修改 根据上述as_matrix()文档的最后一句,将values更改为as_matrix(),(它不会更改结果):

  

通常,建议使用'.values'。

import pandas as pd
import numpy as np #for the random integer example
df = pd.DataFrame(np.random.randint(0.0,100.0,size=(10,4)),
              index=range(10,20),
              columns=['col1','col2','col3','col4'],
              dtype='float64')

注意,指数是10-19:

In [14]: df.head(3)
Out[14]:
    col1    col2    col3    col4
    10  3   38  86  65
    11  98  3   66  68
    12  88  46  35  68

现在fit_transform DataFrame获取scaled_features array

from sklearn.preprocessing import StandardScaler
scaled_features = StandardScaler().fit_transform(df.values)

In [15]: scaled_features[:3,:] #lost the indices
Out[15]:
array([[-1.89007341,  0.05636005,  1.74514417,  0.46669562],
       [ 1.26558518, -1.35264122,  0.82178747,  0.59282958],
       [ 0.93341059,  0.37841748, -0.60941542,  0.59282958]])

将缩放数据分配给DataFrame(注意:使用indexcolumns关键字参数来保留原始索引和列名称:

scaled_features_df = pd.DataFrame(scaled_features, index=df.index, columns=df.columns)

In [17]:  scaled_features_df.head(3)
Out[17]:
    col1    col2    col3    col4
10  -1.890073   0.056360    1.745144    0.466696
11  1.265585    -1.352641   0.821787    0.592830
12  0.933411    0.378417    -0.609415   0.592830

编辑2:

来到sklearn-pandas包裹。它专注于让scikit-learn更容易与熊猫一起使用。当您需要将多种类型的转换应用于sklearn-pandas的列子集时,DataFrame特别有用,这是一种更常见的方案。它已被记录,但这就是您实现我们刚刚执行的转换的方式。

from sklearn_pandas import DataFrameMapper

mapper = DataFrameMapper([(df.columns, StandardScaler())])
scaled_features = mapper.fit_transform(df.copy(), 4)
scaled_features_df = pd.DataFrame(scaled_features, index=df.index, columns=df.columns)

答案 1 :(得分:5)

import pandas as pd    
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('your file here')
ss = StandardScaler()
df_scaled = pd.DataFrame(ss.fit_transform(df),columns = df.columns)

df_scaled将是“相同”的数据框,只是现在具有缩放值

答案 2 :(得分:4)

features = ["col1", "col2", "col3", "col4"]
autoscaler = StandardScaler()
df[features] = autoscaler.fit_transform(df[features])

答案 3 :(得分:1)

这就是我所做的:

X.Column1 = StandardScaler().fit_transform(X.Column1.values.reshape(-1, 1))

答案 4 :(得分:1)

重新分配回 df.values 会保留索引和列。

df.values[:] = StandardScaler().fit_transform(df)

答案 5 :(得分:0)

您可以使用Neuraxle在scikit-learn中混合使用多种数据类型:

选项1:丢弃行名和列名

from neuraxle.pipeline import Pipeline
from neuraxle.base import NonFittableMixin, BaseStep

class PandasToNumpy(NonFittableMixin, BaseStep):
    def transform(self, data_inputs, expected_outputs): 
        return data_inputs.values

pipeline = Pipeline([
    PandasToNumpy(),
    StandardScaler(),
])

然后,您按预期进行:

features = df[["col1", "col2", "col3", "col4"]]  # ... your df data
pipeline, scaled_features = pipeline.fit_transform(features)

选项2:保留原始的列名和行名

您甚至可以使用包装器来做到这一点:

from neuraxle.pipeline import Pipeline
from neuraxle.base import MetaStepMixin, BaseStep

class PandasValuesChangerOf(MetaStepMixin, BaseStep):
    def transform(self, data_inputs, expected_outputs): 
        new_data_inputs = self.wrapped.transform(data_inputs.values)
        new_data_inputs = self._merge(data_inputs, new_data_inputs)
        return new_data_inputs

    def fit_transform(self, data_inputs, expected_outputs): 
        self.wrapped, new_data_inputs = self.wrapped.fit_transform(data_inputs.values)
        new_data_inputs = self._merge(data_inputs, new_data_inputs)
        return self, new_data_inputs

    def _merge(self, data_inputs, new_data_inputs): 
        new_data_inputs = pd.DataFrame(
            new_data_inputs,
            index=data_inputs.index,
            columns=data_inputs.columns
        )
        return new_data_inputs

df_scaler = PandasValuesChangerOf(StandardScaler())

然后,您按预期进行:

features = df[["col1", "col2", "col3", "col4"]]  # ... your df data
df_scaler, scaled_features = df_scaler.fit_transform(features)

答案 6 :(得分:-1)

您可以尝试这段代码,这将为您提供一个带有索引的DataFrame

import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_boston # boston housing dataset

dt= load_boston().data
col= load_boston().feature_names

# Make a dataframe
df = pd.DataFrame(data=dt, columns=col)

# define a method to scale data, looping thru the columns, and passing a scaler
def scale_data(data, columns, scaler):
    for col in columns:
        data[col] = scaler.fit_transform(data[col].values.reshape(-1, 1))
    return data

# specify a scaler, and call the method on boston data
scaler = StandardScaler()
df_scaled = scale_data(df, col, scaler)

# view first 10 rows of the scaled dataframe
df_scaled[0:10]

答案 7 :(得分:-1)

您可以使用切片直接将 numpy 数组分配给数据框。

from sklearn.preprocessing import StandardScaler
features = df[["col1", "col2", "col3", "col4"]]
autoscaler = StandardScaler()
features[:] = autoscaler.fit_transform(features.values)