J'ai un dataframe pandas avec des colonnes de type mixte, et j'aimerais appliquer min_max_scaler de sklearn à certaines des colonnes. Idéalement, j'aimerais faire ces transformations en place, mais je n'ai pas encore trouvé de moyen de le faire. 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 la manière préférée / la plus efficace de faire cette transformation. Y a-t-il un moyen d'utiliser df.apply qui serait mieux?
Je suis également surpris de ne pas pouvoir faire fonctionner le code suivant:
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 ne comprends pas pourquoi la transmission d'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 = sur la série mise à l'échelle. J'ai vu cette question posée à quelques autres endroits, mais je n'ai pas trouvé de bonne réponse. Toute aide pour comprendre ce qui se passe ici serait grandement appréciée!
la source
bad_output = min_max_scaler.fit_transform(dfTest['A'].values)
? l'accès à l'values
attribut renvoie un tableau numpy, pour une raison quelconque, l'api scikit learn appellera correctement la bonne méthode qui fait que les pandas retournent un tableau numpy et parfois ce n'est pas le cas.bad_output = in_max_scaler.fit_transform(dfTest['A'].values)
n'a pas fonctionné non plus. @larsmans - ouais, j'avais pensé à emprunter cette voie, cela semble juste être un problème. Je ne sais pas si c'est un bogue ou non que les Pandas peuvent passer une trame de données complète à une fonction sklearn, mais pas une série. Ma compréhension d'un dataframe était qu'il s'agit d'un dict de série. En lisant le livre "Python for Data Analysis", il indique que pandas est construit sur numpy pour le rendre facile à utiliser dans les applications centrées sur NumPy.Réponses:
Je ne sais pas si les versions précédentes de l'ont
pandas
empêché, mais maintenant l'extrait de code suivant fonctionne parfaitement pour moi et produit exactement ce que vous voulez sans avoir à utiliserapply
la source
df[df.columns] = scaler.fit_transform(df[df.columns])
__getitem__
méthode. Plus précisément, vous pouvez ouvrir votre ipython et fairepd.DataFrame.__getitem__??
; après avoir importé des pandas en tant que pd bien sûr;)columns =df.columns.drop('timestamps') df[df.columns] = scaler.fit_transform(df[df.columns]
Comme ça?
la source
Comme il est mentionné dans le commentaire de pir - la
.apply(lambda el: scale.fit_transform(el))
méthode produira l'avertissement suivant:La conversion de vos colonnes en tableaux numpy devrait faire le travail (je préfère StandardScaler):
- Edit Nov 2018 (Testé pour les pandas 0.23.4 ) -Comme Rob Murray le mentionne dans les commentaires, dans la version actuelle (v0.23.4) de pandas
.as_matrix()
revientFutureWarning
. Par conséquent, il doit être remplacé par.values
:- Edit mai 2019 (Testé pour les pandas 0.24.2 ) -
Comme le mentionne joelostblom dans les commentaires, "Depuis
0.24.0
, il est recommandé d'utiliser à la.to_numpy()
place de.values
."Exemple mis à jour:
la source
.values
à la place de.as_matrix()
commeas_matrix()
donne maintenant unFutureWarning
.0.24.0
, il est recommandé d'utiliser à la.to_numpy()
place de.values
.Cela devrait fonctionner sans avertissements de dépréciation.
la source
Vous pouvez le faire en utilisant
pandas
uniquement:la source
df.max() - df.min()
peut être égale à 0, entraînant une exception. De plus,df.min()
est calculé deux fois, ce qui est inefficace. Notez que celadf.ptp()
équivaut àdf.max() - df.min()
.Je sais que c'est un très vieux commentaire, mais quand même:
Au lieu d'utiliser un support simple
(dfTest['A'])
, utilisez des supports doubles(dfTest[['A']])
.à savoir:
min_max_scaler.fit_transform(dfTest[['A']])
.Je pense que cela donnera le résultat souhaité.
la source