Как использовать sklearn fit_transform с pandas и вернуть dataframe вместо массива numpy?

Я хочу применить масштабирование (используя StandardScaler() из sklearn.preprocessing) в фреймворк pandas. Следующий код возвращает массив numpy, поэтому я теряю все имена столбцов и индексы. Это не то, что я хочу.

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

"Решение", которое я нашел в Интернете, это:

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

Кажется, что он работает, но приводит к устаревшему предупреждению:

/usr/lib/python3.5/site-packages/sklearn/preprocessing/data.py:583: Устаревшее предупреждение: передача 1-го массива в качестве устаревших данных в 0.17 и повысит ValueError в 0.19. Измените данные, используя X.reshape(-1, 1), если ваши данные имеют одну функцию или X.resape(1, -1) если он содержит один образец.

Поэтому я попытался:

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

Но это дает:

Traceback (последний последний вызов): Файл "./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) Файл "/usr/lib/python3.5/site-packages/pandas/core/frame.py" , строка 4081, в _apply_standard     result = self._constructor (data = results, index = index) Файл "/usr/lib/python3.5/site-packages/pandas/core/frame.py" , строка 226, в INIT    mgr = self._init_dict (данные, индекс, столбцы, dtype = dtype) Файл "/usr/lib/python3.5/site-packages/ pandas/core/frame.py" , строка 363, в _init_dict     dtype = dtype) Файл "/usr/lib/python3.5/site-packages/pandas/core/frame.py" , строка 5163, в _arrays_to_mgr     массивы = _homogenize (массивы, индекс, dtype) Файл "/usr/lib/python3.5/site-packages/pandas/core/frame.py" , строка 5477, в _homogenize     raise_cast_failure = False) Файл "/usr/lib/python3.5/site-packages/pandas/core/series.py", строка 2885, в _sanitize_array     raise Exception ( "Данные должны быть одномерными" ) Исключение: данные должны быть одномерными

Как применить масштабирование к фреймворку pandas, оставив нет данных? Без копирования данных, если это возможно.

Ответ 1

Вы можете преобразовать DataFrame в массив numpy, используя as_matrix(). Пример случайного набора данных:

Edit: Изменение as_matrix() на values (оно не меняет результат) в последнем предложении as_matrix() docs выше:

Как правило, рекомендуется использовать ".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 (Примечание: используйте аргументы ключевого слова index и columns, чтобы сохранить исходные индексы и имена столбцов:

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 более удобным для использования с pandas. 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)