web-dev-qa-db-ja.com

パンダデータフレームの列を正規化する

各列の値の範囲が異なるパンダのデータフレームがあります。例えば:

df:

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

各値が0と1の間にある場合、このデータフレームの列を正規化するにはどうすればよいですか。

私が望む出力は:

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

Sklearnパッケージとそれに関連する前処理ユーティリティを使ってデータを正規化することができます。

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)

詳細については、データの前処理に関するscikit-learn のドキュメント を参照してください。

125
Sandman

Pandasを使用した簡単な方法:(ここでは平均正規化を使用します)

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

最小 - 最大正規化を使用するには:

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

この投稿に基づく: https://stats.stackexchange.com/questions/70801/how-to-normalize-data-to-0-1-range

次のことができます。

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

自分の価値観がマイナスかプラスかを心配する必要はありません。そして値は0と1の間にうまく分散されるべきです。

37

Sklearnパッケージを使用したい場合は、次のようにパンダlocを使用して列名とインデックス名を保持できます。

from sklearn.preprocessing import MinMaxScaler

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

あなたの問題は実際には列に作用する単純な変換です。

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

frame.apply(f, axis=0)

またはもっともっと簡潔:

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

シンプルは美しい:

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

正規化したい列のリストを作成することができます

column_names_to_normalize = ['A', 'E', 'G', 'sadasdsd', 'lol']
x = df[column_names_to_normalize].values
x_scaled = min_max_scaler.fit_transform(x)
df_temp = pd.DataFrame(x_scaled, columns=column_names_to_normalize, index = df.index)
df[column_names_to_normalize] = df_temp

Pandasデータフレームは、必要な列でのみ正規化されるようになりました


ただし、、反対のが必要な場合は、その列のリストを選択します。あなたいけない正規化したくない場合は、単にすべての列のリストを作成し、その不要な列を削除することができます。

column_names_to_not_normalize = ['B', 'J', 'K']
column_names_to_normalize = [x for x in list(df) if x not in column_names_to_not_normalize ]
13
raullalves

私はパンダでそれをするためのより良い方法がちょうどだと思います

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

編集データフレームに負の数がある場合は代わりに使うべきです

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

SandmanとPraveenによって与えられた解決策は非常に順調です。データフレームの他の列にカテゴリカル変数がある場合、これに関する唯一の問題は、この方法でいくつか調整が必要になることです。

この種の問題に対する私の解決策は次のとおりです。

 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

データラベルやカテゴリカル列が変更されていない回帰タスクのように、一部の列を正規化し、他の列を変更しないことをお勧めします。

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)

パンダのドキュメントから、DataFrame構造体はそれ自身に操作(関数)を適用することができます。

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

DataFrameの入力軸に沿って関数を適用します。関数に渡されるオブジェクトは、DataFrameのインデックス(axis = 0)またはカラム(axis = 1)のいずれかのインデックスを持つSeriesオブジェクトです。戻り値の型は、渡された関数が集約するかどうか、またはDataFrameが空の場合はreduce引数によって異なります。

DataFrameを操作するためにカスタム関数を適用することができます。

1
shg

Sklearnは標準偏差にバイアス推定器を使用することに注意してください。次の正規化の例を検討してください。

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

正規化する場合、単純に平均値を引き、標準偏差で除算します。

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

sklearnで同じことを行うと、異なる出力が得られます!

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

結果は異なります。ただし、バイアス推定器を使用したsklearn.preprocessing.scaleの公式ドキュメントによると、機械学習アルゴリズムのパフォーマンスに影響を与えることはほとんどなく、安全に使用できます。

1
Poudel

次の関数は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
1
user260826

あなたは一行でこれを行うことができます

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

それは各列の平均を取り、それから各行からそれを減算し(平均)(特定の列の平均がその行のみから減算する)そして平均のみで除算する。最後に、正規化されたデータセットが得られます。

0
Rishi Bansal

単純な数学です。答えは以下のように簡単なはずです。

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

これは、リスト内包表記を使用して列ごとに行う方法です。

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