Pandas Dataframe で列を正規化する

Sathiya Sarathi 2023年10月10日
  1. Pandas でのデータ正規化
  2. Pandas の DataFrame を mean 正規化で正規化する
  3. 最小値と最大値の正規化で Pandas の DataFrame を正規化する
  4. 分位正規化を使用して Pandas Dataframe を正規化する
Pandas Dataframe で列を正規化する

データの標準化または正規化は、フィーチャーエンジニアリングの最初のステップです。カラムの正規化では、カラムの値を共通の尺度に持ってくる必要があり、主に範囲が変化するカラムに対して行われます。Pandas では、DataFrame のカラムはさまざまな関数を使って正規化することができます。この記事では、これらの関数を練習し、適切な状況で関数を適用するのに役立ちます。

Pandas でのデータ正規化

データの正規化には、最も広く使われている 2つの方法があります。

  • 平均正規化
  • 最小-最大正規化
  • 分位正規化

Pandas では、データの正規化を行うための特定のメソッドが用意されていません。今回は、これらの正規化とは何か、そしてどのように実装できるのかを、ネイティブの Pandas と、ネイティブの Python 関数を少し触って説明します。

随所に以下のスニペットを使用して、以下のようにランダムな要素を持つ DataFrame を作成します。

import pandas as pd
import numpy as np

np.random.seed(0)

df = pd.DataFrame(np.random.randint(-100, 100, size=(20, 4)), columns=list("ABCD"))
print(df)

これは以下のような DataFrame を返します。

     A   B   C   D
0   72 -53  17  92
1  -33  95   3 -91
2  -79 -64 -13 -30
3  -12  40 -42  93
4  -61 -13  74 -12
5  -19  65 -75 -23
6  -28 -91  48  15
7   97 -21  75  92
8  -18  -1  77 -71
9   47  47  42  67
10 -68  93 -91  85
11  27 -68 -69  51
12  63  14  83 -72
13 -66  28  28  64
14 -47  33 -62 -83
15 -21  32   5 -58
16  86 -69  20 -99
17 -35  69 -43 -65
18   2  19 -89  74
19 -18  -9  28  42

[20 rows x 4 columns]

Pandas の DataFrame を mean 正規化で正規化する

平均値の正規化は、様々な範囲の DataFrame を正規化する最も簡単な方法の一つです。正規化は、DataFrame のすべての要素から平均値を引き、標準偏差で割ることで行われます。

import pandas as pd
import numpy as np

np.random.seed(0)

df = pd.DataFrame(np.random.randint(-100, 100, size=(20, 4)), columns=list("ABCD"))


def mean_norm(df_input):
    return df_input.apply(lambda x: (x - x.mean()) / x.std(), axis=0)


df_mean_norm = mean_norm(df)
print(df_mean_norm)

出力:

           A         B         C         D
0   1.452954 -1.090261  0.278088  1.247208
1  -0.514295  1.585670  0.037765 -1.333223
2  -1.376137 -1.289148 -0.236890 -0.473079
3  -0.120845  0.591236 -0.734701  1.261309
4  -1.038895 -0.367037  1.256545 -0.219266
5  -0.251995  1.043252 -1.301176 -0.374374
6  -0.420617 -1.777325  0.810231  0.161453
7   1.921346 -0.511681  1.273711  1.247208
8  -0.233260 -0.150069  1.308043 -1.051208
9   0.984561  0.717801  0.707236  0.894690
10 -1.170045  1.549509 -1.575831  1.148503
11  0.609847 -1.361470 -1.198181  0.669079
12  1.284333  0.121140  1.411038 -1.065309
13 -1.132573  0.374269  0.466913  0.852388
14 -0.776595  0.464672 -1.078020 -1.220417
15 -0.289467  0.446591  0.072097 -0.867899
16  1.715254 -1.379551  0.329586 -1.446028
17 -0.551766  1.115574 -0.751867 -0.966604
18  0.141455  0.211543 -1.541499  0.993395
19 -0.233260 -0.294714  0.466913  0.542172

Jupyter ノートブックを使っている場合、以下のコードに示すように、Matplotlib を使って両方の DataFrame を可視化することができます。

# %matplotlib inline
df["A"].plot(kind="bar")

正規化前の DataFrame の列 A を選択して棒グラフを可視化すると、y 軸に-100 から 100 の範囲の値が含まれていることに気づきます。

平均正規化 - 正規化前

# %matplotlib inline
df_mean_norm["A"].plot(kind="bar")

下図は正規化後のデータを示しており、同じ列を可視化した場合、y 軸は-1.5~+1.5 の範囲にあります。

平均正規化 - 正規化後

最小値と最大値の正規化で Pandas の DataFrame を正規化する

正規化のために広く使われている方法の一つです。正規化出力は、DataFrame の最小値を差し引き、対応する列の最高値と最低値の差で除算します。

import pandas as pd
import numpy as np

np.random.seed(0)

df = pd.DataFrame(np.random.randint(-100, 100, size=(20, 4)), columns=list("ABCD"))


def minmax_norm(df_input):
    return (df - df.min()) / (df.max() - df.min())


df_minmax_norm = minmax_norm(df)

print(df_minmax_norm)

出力:

           A         B         C         D
0   0.857955  0.204301  0.620690  0.994792
1   0.261364  1.000000  0.540230  0.041667
2   0.000000  0.145161  0.448276  0.359375
3   0.380682  0.704301  0.281609  1.000000
4   0.102273  0.419355  0.948276  0.453125
5   0.340909  0.838710  0.091954  0.395833
6   0.289773  0.000000  0.798851  0.593750
7   1.000000  0.376344  0.954023  0.994792
8   0.346591  0.483871  0.965517  0.145833
9   0.715909  0.741935  0.764368  0.864583
10  0.062500  0.989247  0.000000  0.958333
11  0.602273  0.123656  0.126437  0.781250
12  0.806818  0.564516  1.000000  0.140625
13  0.073864  0.639785  0.683908  0.848958
14  0.181818  0.666667  0.166667  0.083333
15  0.329545  0.661290  0.551724  0.213542
16  0.937500  0.118280  0.637931  0.000000
17  0.250000  0.860215  0.275862  0.177083
18  0.460227  0.591398  0.011494  0.901042
19  0.346591  0.440860  0.683908  0.734375

上記の出力では、各列の最小値は 0 に変換され、各列の最大値は 1 に変換されます。

この正規化のための列 A は以下のように可視化されています。

# %matplotlib inline
df_minmax_norm["A"].plot(kind="bar")

最小値と最大値の正規化 - 正規化後

これは、近い距離の DataFrame には適していますが、外れ値の多い DataFrame には、MinMax 正規化は適していないかもしれません。

分位正規化を使用して Pandas Dataframe を正規化する

分位正規化は、高次元データ分析の場合に使用されています。これは、各列の統計分布が 1つで同じであることを観察し、仮定します。分位正規化は、以下のステップで構成されています。

  1. 各列内での値の順序付け(順位付け
  2. 各行の平均化を行い、行内の各要素の値を平均値に置き換えます。
  3. 値の順序を最初の順序に戻します。
import numpy as np
import pandas as pd

np.random.seed(0)

df = pd.DataFrame(np.random.randint(-100, 100, size=(20, 4)), columns=list("ABCD"))


def quantile_norm(df_input):
    sorted_df = pd.DataFrame(
        np.sort(df_input.values, axis=0), index=df_input.index, columns=df_input.columns
    )
    mean_df = sorted_df.mean(axis=1)
    mean_df.index = np.arange(1, len(mean_df) + 1)
    quantile_df = df_input.rank(method="min").stack().astype(int).map(mean_df).unstack()
    return quantile_df


df_quantile_norm = quantile_norm(df)

print(df_quantile_norm)

出力:

        A      B      C      D
0   77.00 -58.25   8.25  77.00
1  -36.50  92.00 -10.50 -79.25
2  -90.00 -66.50 -20.00 -20.00
3   24.75  44.00 -36.50  92.00
4  -66.50 -36.50  71.75  -3.00
5   -3.00  71.75 -73.00 -10.50
6  -20.00 -90.00  54.00   8.25
7   92.00 -41.00  77.00  77.00
8    8.25 -10.50  87.00 -58.25
9   54.00  54.00  44.00  44.00
10 -79.25  87.00 -90.00  71.75
11  44.00 -73.00 -66.50  24.75
12  71.75  -3.00  92.00 -66.50
13 -73.00  18.00  24.75  31.75
14 -58.25  31.75 -58.25 -73.00
15 -10.50  24.75  -3.00 -36.50
16  87.00 -79.25  18.00 -90.00
17 -41.00  77.00 -41.00 -41.00
18  31.75   8.25 -79.25  54.00
19   8.25 -20.00  24.75  18.00

分位正規化の出力は、以下のように A 列について可視化することができます。

分位正規化 - 正規化後

関連記事 - Pandas DataFrame

関連記事 - Pandas DataFrame Column