web-dev-qa-db-fra.com

Normaliser les colonnes du cadre de données des pandas

J'ai une base de données dans les pandas où chaque colonne a une plage de valeurs différente. Par exemple:

df:

A     B   C
1000  10  0.5
765   5   0.35
800   7   0.09

Avez-vous une idée de la façon dont je peux normaliser les colonnes de cette image de données où chaque valeur est comprise entre 0 et 1?

Ma sortie souhaitée est:

A     B    C
1     1    1
0.765 0.5  0.7
0.8   0.7  0.18(which is 0.09/0.5)
104
ahajib

Vous pouvez utiliser le package sklearn et ses utilitaires de prétraitement associés pour normaliser les données.

from sklearn import preprocessing

x = df.values #returns a numpy array
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
df = pandas.DataFrame(x_scaled)

Pour plus d'informations, consultez scikit-learn documentation sur le prétraitement des données: mise à l'échelle des fonctionnalités sur une plage.

108
Sandman

un moyen facile en utilisant Pandas : (ici je veux utiliser la normalisation moyenne)

normalized_df=(df-df.mean())/df.std()

utiliser la normalisation min-max:

normalized_df=(df-df.min())/(df.max()-df.min())
184
Cina

Basé sur ce post: https://stats.stackexchange.com/questions/70801/how-to-normalize-data-to-0-1-range

Vous pouvez faire ce qui suit:

def normalize(df):
    result = df.copy()
    for feature_name in df.columns:
        max_value = df[feature_name].max()
        min_value = df[feature_name].min()
        result[feature_name] = (df[feature_name] - min_value) / (max_value - min_value)
    return result

Vous n'avez pas besoin de rester inquiet pour savoir si vos valeurs sont négatives ou positives. Et les valeurs doivent être bien réparties entre 0 et 1.

35
Michael Aquilina

Si vous aimez utiliser le package sklearn, vous pouvez conserver les noms de colonne et d’index en utilisant pandas loc comme ceci:

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler() 
scaled_values = scaler.fit_transform(df) 
df.loc[:,:] = scaled_values
19
j sad

Votre problème est en réalité une simple transformation agissant sur les colonnes:

def f(s):
    return s/s.max()

frame.apply(f, axis=0)

Ou même plus laconique:

   frame.apply(lambda x: x/x.max(), axis=0)
18
tschm

Le simple est beau:

df["A"] = df["A"] / df["A"].max()
df["B"] = df["B"] / df["B"].max()
df["C"] = df["C"] / df["C"].max()
12
Basil Musa

Je pense qu’un meilleur moyen de le faire chez les pandas est juste

df = df/df.max().astype(np.float64)

Edit Si dans votre bloc de données, des nombres négatifs sont présents, vous devriez utiliser

df = df/df.loc[df.abs().idxmax()].astype(np.float64)
8
Daniele

La solution donnée par Sandman et Praveen est très bien. Le seul problème avec cela, si vous avez des variables catégorielles dans d'autres colonnes de votre base de données, cette méthode nécessitera quelques ajustements. 

Ma solution à ce type de problème est la suivante:

 from sklearn import preprocesing
 x = pd.concat([df.Numerical1, df.Numerical2,df.Numerical3])
 min_max_scaler = preprocessing.MinMaxScaler()
 x_scaled = min_max_scaler.fit_transform(x)
 x_new = pd.DataFrame(x_scaled)
 df = pd.concat([df.Categoricals,x_new])
6
cyber-math

Vous voudrez peut-être que certaines colonnes soient normalisées et que d'autres soient inchangées, comme certaines tâches de régression dont les étiquettes de données ou les colonnes catégoriques ne sont pas modifiées. Je vous suggère donc cette méthode pythonique (combinaison des réponses @shg et @Cina):

features_to_normalize = ['A', 'B', 'C']
# could be ['A','B'] 

df[features_to_normalize] = df[features_to_normalize].apply(lambda x:(x-x.min()) / (x.max()-x.min()))
def normalize(x):
    try:
        x = x/np.linalg.norm(x,ord=1)
        return x
    except :
        raise
data = pd.DataFrame.apply(data,normalize)

À partir du document de pandas, la structure DataFrame peut s’appliquer à une opération (fonction).

DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)

Applique une fonction le long de l’axe de saisie de DataFrame . Les objets transmis aux fonctions sont des objets Series ayant pour index l’index de DataFrame (axis = 0) ou les colonnes (axis = 1). Le type de retour dépend de l'agrégation de la fonction transmise ou de l'argument de réduction si le DataFrame est vide.

Vous pouvez appliquer une fonction personnalisée pour utiliser le DataFrame. 

1
shg

Notez que sklearn utilise un estimateur biaisé pour l'écart type. Envisagez de suivre l'exemple suivant:

import pandas as pd
df = pd.DataFrame({
               'A':[1,2,3],
               'B':[100,300,500],
               'C':list('abc')
             })
print(df)
   A    B  C
0  1  100  a
1  2  300  b
2  3  500  c

Lors de la normalisation, nous soustrayons simplement la moyenne et divisons par l'écart-type.

df.iloc[:,0:-1] = df.iloc[:,0:-1].apply(lambda x: (x-x.mean())/ x.std(), axis=0)
print(df)
     A    B  C
0 -1.0 -1.0  a
1  0.0  0.0  b
2  1.0  1.0  c

Si vous faites la même chose avec sklearn vous obtiendrez une sortie DIFFERENTE!

import pandas as pd

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()


df = pd.DataFrame({
               'A':[1,2,3],
               'B':[100,300,500],
               'C':list('abc')
             })
df.iloc[:,0:-1] = scaler.fit_transform(df.iloc[:,0:-1].to_numpy())
print(df)
          A         B  C
0 -1.224745 -1.224745  a
1  0.000000  0.000000  b
2  1.224745  1.224745  c

Les résultats sont différents. Toutefois, conformément à la documentation officielle de sklearn.preprocessing.scale, l’estimateur biaisé est IMPLICABLE d’affecter les performances des algorithmes d’apprentissage automatique et nous pouvons les utiliser en toute sécurité.

1
Poudel

Vous pouvez le faire en une seule ligne

DF_test = DF_test.sub(DF_test.mean(axis=0), axis=1)/DF_test.mean(axis=0)

il prend moyenne pour chaque colonne, puis la soustrait (moyenne) de chaque ligne (la moyenne d'une colonne particulière soustrait uniquement de sa ligne) et ne divise que par moyenne. Enfin, nous obtenons l’ensemble de données normalisé.

0
Rishi Bansal

Ce ne sont que des mathématiques simples. La réponse devrait être aussi simple que ci-dessous.

normed_df = (df - df.min()) / (df.max() - df.min())
0
Yuan

Voici comment procéder en colonne en utilisant la compréhension de liste:

[df[col].update((df[col] - df[col].min()) / (df[col].max() - df[col].min())) for col in df.columns]
0
Chad

La fonction suivante calcule le score Z:

def standardization(dataset):
  """ Standardization of numeric fields, where all values will have mean of zero 
  and standard deviation of one. (z-score)

  Args:
    dataset: A `Pandas.Dataframe` 
  """
  dtypes = list(Zip(dataset.dtypes.index, map(str, dataset.dtypes)))
  # Normalize numeric columns.
  for column, dtype in dtypes:
      if dtype == 'float32':
          dataset[column] -= dataset[column].mean()
          dataset[column] /= dataset[column].std()
  return dataset
0
spicyramen