pandas DataFrame colonnes mise à l'échelle avec sklearn
J'ai un DataFrame pandas avec des colonnes de type mixte, et je voudrais appliquer min_max_scaler de sklearn à certaines des colonnes. Idéalement, j'aimerais faire ces transformations en place, mais n'avez pas trouvé un moyen de le faire encore. J'ai écrit le code suivant qui fonctionne:
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
Je suis curieux de savoir si c'est le moyen préféré/le plus efficace de faire cette transformation. Y at-il un moyen que je pourrais utiliser df.appliquer ce serait mieux?
Je suis aussi surpris que je ne puisse pas obtenir ce qui suit code à travailler:
bad_output = min_max_scaler.fit_transform(dfTest['A'])
Si je passe un dataframe entier au scaler, cela fonctionne:
dfTest2 = dfTest.drop('C', axis = 1)
good_output = min_max_scaler.fit_transform(dfTest2)
good_output
Je suis confus pourquoi passer une série au scaler échoue. Dans mon code de travail complet ci-dessus, j'avais espéré simplement passer une série au scaler puis définir la colonne dataframe = à la série mise à l'échelle. J'ai vu cette question posée à quelques autres endroits, mais je n'ai pas trouvé une bonne réponse. Toute aide à comprendre ce qui se passe ici serait grandement appréciée!
4 réponses
Je ne suis pas sûr si les versions précédentes de pandas
l'ont empêché mais maintenant l'extrait suivant fonctionne parfaitement pour moi et produit exactement ce que vous voulez sans avoir à utiliser apply
>>> import pandas as pd
>>> from sklearn.preprocessing import MinMaxScaler
>>> scaler = 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']})
>>> dfTest[['A', 'B']] = scaler.fit_transform(dfTest[['A', 'B']])
>>> dfTest
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
Comme ça?
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']
})
dfTest[['A','B']] = dfTest[['A','B']].apply(
lambda x: MinMaxScaler().fit_transform(x))
dfTest
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
Vous pouvez le faire en utilisant pandas
seulement:
In [235]:
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']})
df = dfTest[['A', 'B']]
df_norm = (df - df.min()) / (df.max() - df.min())
print df_norm
print pd.concat((df_norm, dfTest.C),1)
A B
0 0.000000 0.000000
1 0.926219 0.363636
2 0.935335 0.628645
3 1.000000 0.961407
4 0.938495 1.000000
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
Comme il est mentionné dans le commentaire de pir - La Méthode .apply(lambda el: scale.fit_transform(el))
produira l'avertissement suivant:
DeprecationWarning: passer des tableaux 1d car les données sont obsolètes dans 0.17 et augmentera ValueError dans 0.19. Remodelez vos données soit en utilisant X. reshape (-1, 1) si vos données ont une seule fonctionnalité ou X. reshape (1, -1) si elle contient un seul échantillon.
Convertir vos colonnes en tableaux numpy devrait faire le travail (je préfère StandardScaler):
from sklearn.preprocessing import StandardScaler
scale = StandardScaler()
dfTest[['A','B','C']] = scale.fit_transform(dfTest[['A','B','C']].as_matrix())