Eu tenho um dataframe de pandas com colunas de tipo misto e gostaria de aplicar o min_max_scaler do sklearn a algumas das colunas. Idealmente, eu gostaria de fazer essas transformações no local, mas ainda não descobri uma maneira de fazer isso. Eu escrevi o seguinte código que funciona:
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
Estou curioso para saber se essa é a maneira preferida / mais eficiente de fazer essa transformação. Existe uma maneira que eu poderia usar df.apply que seria melhor?
Também estou surpreso por não conseguir que o seguinte código funcione:
bad_output = min_max_scaler.fit_transform(dfTest['A'])
Se eu passar um quadro de dados inteiro para o scaler, ele funcionará:
dfTest2 = dfTest.drop('C', axis = 1)
good_output = min_max_scaler.fit_transform(dfTest2)
good_output
Estou confuso por que a passagem de uma série para o scaler falha. No meu código de trabalho completo acima, eu esperava apenas passar uma série para o scaler e depois definir a coluna dataframe = para a série escalada. Eu já vi essa pergunta em alguns outros lugares, mas não encontrei uma boa resposta. Qualquer ajuda para entender o que está acontecendo aqui seria muito apreciada!
fonte
bad_output = min_max_scaler.fit_transform(dfTest['A'].values)
? acessar ovalues
atributo retorna uma matriz numpy; por algum motivo, às vezes a API do scikit learn chama corretamente o método certo que faz com que os pandas retornem uma matriz numpy e outras vezes não.bad_output = in_max_scaler.fit_transform(dfTest['A'].values)
também não funcionou. @ Larsmans - Sim, eu tinha pensado em ir por este caminho, parece apenas um aborrecimento. Não sei se é um bug ou não que o Pandas possa transmitir um quadro de dados completo para uma função sklearn, mas não uma série. Meu entendimento de um quadro de dados era que ele era um ditado de série. Lendo o livro "Python para Análise de Dados", ele afirma que o pandas é construído sobre o numpy para facilitar o uso em aplicações centradas no NumPy.Respostas:
Não sei se as versões anteriores
pandas
impediram isso, mas agora o seguinte trecho funciona perfeitamente para mim e produz exatamente o que você deseja, sem precisar usarapply
fonte
df[df.columns] = scaler.fit_transform(df[df.columns])
__getitem__
método. Especificamente, você pode abrir o ipython e fazerpd.DataFrame.__getitem__??
; depois de importar pandas como pd, é claro;)columns =df.columns.drop('timestamps') df[df.columns] = scaler.fit_transform(df[df.columns]
Como isso?
fonte
Como está sendo mencionado no comentário do pir - o
.apply(lambda el: scale.fit_transform(el))
método produzirá o seguinte aviso:A conversão de suas colunas em matrizes numpy deve fazer o trabalho (eu prefiro StandardScaler):
- Editar novembro de 2018 (testado para pandas 0.23.4 ) -Como Rob Murray menciona nos comentários, na versão atual (v0.23.4) dos pandas
.as_matrix()
retornaFutureWarning
. Portanto, deve ser substituído por.values
:- Editar maio de 2019 (testado para pandas 0.24.2 ) -
Como joelostblom menciona nos comentários, "Desde então
0.24.0
, é recomendável usar em.to_numpy()
vez de.values
".Exemplo atualizado:
fonte
.values
no lugar de.as_matrix()
comoas_matrix()
agora dá aFutureWarning
.0.24.0
, é recomendável usar em.to_numpy()
vez de.values
.Isso deve funcionar sem avisos de depreciação.
fonte
Você pode fazer isso usando
pandas
apenas:fonte
df.max() - df.min()
pode ser 0, levando a uma exceção. Além disso,df.min()
é calculado duas vezes, o que é ineficiente. Note quedf.ptp()
é equivalente adf.max() - df.min()
.Eu sei que é um comentário muito antigo, mas ainda assim:
Em vez de usar colchetes simples
(dfTest['A'])
, use colchetes duplos(dfTest[['A']])
.isto é:
min_max_scaler.fit_transform(dfTest[['A']])
.Eu acredito que isso dará o resultado desejado.
fonte