У меня есть фреймворк pandas со столбцами смешанного типа, и я хотел бы применить min_max_scaler sklearn к некоторым столбцам. В идеале я хотел бы выполнить эти преобразования на месте, но еще не придумал, как это сделать. Я написал следующий код, который работает:
import pandas as pd
import numpy as np
from sklearn import preprocessing
scaler = preprocessing.MinMaxScaler()
dfTest = pd.DataFrame({'A':[14.00,90.20,90.95,96.27,91.21],'B':[103.02,107.26,110.35,114.23,114.68], 'C':['big','small','big','small','small']})
min_max_scaler = preprocessing.MinMaxScaler()
def scaleColumns(df, cols_to_scale):
for col in cols_to_scale:
df[col] = pd.DataFrame(min_max_scaler.fit_transform(pd.DataFrame(dfTest[col])),columns=[col])
return df
dfTest
A B C
0 14.00 103.02 big
1 90.20 107.26 small
2 90.95 110.35 big
3 96.27 114.23 small
4 91.21 114.68 small
scaled_df = scaleColumns(dfTest,['A','B'])
scaled_df
A B C
0 0.000000 0.000000 big
1 0.926219 0.363636 small
2 0.935335 0.628645 big
3 1.000000 0.961407 small
4 0.938495 1.000000 small
Мне любопытно, является ли это предпочтительным / наиболее эффективным способом сделать это преобразование. Есть ли способ использовать df.apply, который был бы лучше?
Я также удивлен, что не могу заставить работать следующий код:
bad_output = min_max_scaler.fit_transform(dfTest['A'])
Если я передаю масштабировщику весь фрейм данных, он работает:
dfTest2 = dfTest.drop('C', axis = 1)
good_output = min_max_scaler.fit_transform(dfTest2)
good_output
Я не понимаю, почему не удается передать серию в скейлер. В моем полном рабочем коде выше я надеялся просто передать серию в масштабирующее устройство, а затем установить столбец dataframe = масштабированной серии. Я видел, как этот вопрос задавали в нескольких других местах, но не нашел хорошего ответа. Любая помощь в понимании того, что здесь происходит, будет принята с благодарностью!
источник
bad_output = min_max_scaler.fit_transform(dfTest['A'].values)
? доступ кvalues
атрибуту возвращает массив numpy, по какой-то причине иногда api scikit learn правильно вызывает правильный метод, который заставляет pandas возвращать массив numpy, а иногда это не так.bad_output = in_max_scaler.fit_transform(dfTest['A'].values)
тоже не заработало. @larsmans - да, я думал о том, чтобы пойти по этому пути, это просто похоже на хлопот. Я не знаю, является ли это ошибкой или нет, что Pandas может передать полный фрейм данных в функцию sklearn, но не серию. Мое понимание фрейма данных заключалось в том, что это диктат серии. В книге «Python для анализа данных» говорится, что pandas построен на основе numpy, чтобы упростить использование в приложениях, ориентированных на NumPy.Ответы:
Я не уверен,
pandas
предотвращали ли это предыдущие версии, но теперь следующий фрагмент отлично работает для меня и дает именно то, что вы хотите, без необходимости использоватьapply
источник
df[df.columns] = scaler.fit_transform(df[df.columns])
__getitem__
метод. В частности, вы можете открыть ipython и выполнитьpd.DataFrame.__getitem__??
; после того, как вы импортируете панд как pd, конечно;)columns =df.columns.drop('timestamps') df[df.columns] = scaler.fit_transform(df[df.columns]
Как это?
источник
Как упоминается в комментарии pir,
.apply(lambda el: scale.fit_transform(el))
метод выдаст следующее предупреждение:Преобразование столбцов в массивы numpy должно сработать (я предпочитаю StandardScaler):
- Редактировать ноябрь 2018 г. (проверено на pandas 0.23.4 ) -Как упоминает Роб Мюррей в комментариях, в текущей (v0.23.4) версии pandas
.as_matrix()
возвращаетсяFutureWarning
. Поэтому его следует заменить на.values
:- Изменить май 2019 г. (проверено для панд 0.24.2 ) -
Как упоминает joelostblom в комментариях: «Так
0.24.0
как рекомендуется использовать.to_numpy()
вместо.values
.»Обновленный пример:
источник
.values
вместо.as_matrix()
какas_matrix()
сейчас даетFutureWarning
.0.24.0
как рекомендуется использовать.to_numpy()
вместо.values
.Это должно работать без предупреждений об амортизации.
источник
Сделать это можно, используя
pandas
только:источник
df.max() - df.min()
может быть 0, что приведет к исключению. Более того,df.min()
вычисляется дважды, что неэффективно. Обратите внимание, чтоdf.ptp()
эквивалентноdf.max() - df.min()
.Я знаю, что это очень старый комментарий, но все же:
Вместо одинарной скобки
(dfTest['A'])
используйте двойные скобки(dfTest[['A']])
.то есть:
min_max_scaler.fit_transform(dfTest[['A']])
.Я верю, что это даст желаемый результат.
источник