Fix Python – How to use sklearn fit_transform with pandas and return dataframe instead of numpy array?


Asked By – Louic

I want to apply scaling (using StandardScaler() from sklearn.preprocessing) to a pandas dataframe. The following code returns a numpy array, so I lose all the column names and indeces. This is not what I want.

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

A “solution” I found online is:

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

It appears to work, but leads to a deprecationwarning:

DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17
and will raise ValueError in 0.19. Reshape your data either using
X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1)
if it contains a single sample.

I therefore tried:

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

But this gives:

Traceback (most recent call last): File “./”, line 91, in

features = features.apply(lambda x: autoscaler.fit_transform(x.reshape(-1, 1))) File
“/usr/lib/python3.5/site-packages/pandas/core/”, line 3972, in
return self._apply_standard(f, axis, reduce=reduce) File “/usr/lib/python3.5/site-packages/pandas/core/”, line 4081, in
result = self._constructor(data=results, index=index) File “/usr/lib/python3.5/site-packages/pandas/core/”, line 226, in
mgr = self._init_dict(data, index, columns, dtype=dtype) File “/usr/lib/python3.5/site-packages/pandas/core/”, line 363, in
dtype=dtype) File “/usr/lib/python3.5/site-packages/pandas/core/”, line 5163, in
arrays = _homogenize(arrays, index, dtype) File “/usr/lib/python3.5/site-packages/pandas/core/”, line 5477, in
raise_cast_failure=False) File “/usr/lib/python3.5/site-packages/pandas/core/”, line 2885,
in _sanitize_array
raise Exception(‘Data must be 1-dimensional’) Exception: Data must be 1-dimensional

How do I apply scaling to the pandas dataframe, leaving the dataframe intact? Without copying the data if possible.

Now we will see solution for issue: How to use sklearn fit_transform with pandas and return dataframe instead of numpy array?


You could convert the DataFrame as a numpy array using as_matrix(). Example on a random dataset:

Changing as_matrix() to values, (it doesn’t change the result) per the last sentence of the as_matrix() docs above:

Generally, it is recommended to use ‘.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)),

Note, indices are 10-19:

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

Now fit_transform the DataFrame to get the scaled_features array:

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

In [15]: scaled_features[:3,:] #lost the indices
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]])

Assign the scaled data to a DataFrame (Note: use the index and columns keyword arguments to keep your original indices and column names:

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

In [17]:  scaled_features_df.head(3)
    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

Edit 2:

Came across the sklearn-pandas package. It’s focused on making scikit-learn easier to use with pandas. sklearn-pandas is especially useful when you need to apply more than one type of transformation to column subsets of the DataFrame, a more common scenario. It’s documented, but this is how you’d achieve the transformation we just performed.

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)

This question is answered By – Kevin

This answer is collected from stackoverflow and reviewed by FixPython community admins, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0