note.nkmk.me

Pythonで正規化・標準化(リスト、NumPy配列、pandas.DataFrame)

Date: 2018-07-29 / tags: Python, リスト, NumPy, pandas, SciPy, scikit-learn

Pythonのリスト(list型)、NumPy配列(numpy.ndarray)、および、pandas.DataFrameを正規化・標準化する方法について説明する。

Python標準ライブラリやNumPy、pandasのメソッドを利用して最大値や最大値、平均、標準偏差を求めて処理することも可能だが、SciPyやscikit-learnでは正規化・標準化のための専用の関数やクラスが用意されている。

以下の内容について説明する。

  • 正規化の種類
  • 正規化・標準化を行うライブラリ
    • SciPy
    • scikit-learn
  • Pythonのリスト(list型オブジェクト)の正規化・標準化
  • NumPy配列ndarrayの正規化・標準化
  • pandas.DataFrame, pandas.Seriesの正規化・標準化
スポンサーリンク

正規化の種類

正規化、正則化、標準化、スケーリングなど様々な用語があるが、ここではその厳密な定義は行わない。

英語でいうところのFeature scalingの処理のうち、以下の2つを対象とし、後者を特に標準化と呼ぶことにする。

最小値0、最大値1に正規化

Min-Max Normalization。

$$ x' = \frac{x - \min{\left( x \right)}}{\max{\left( x \right)} - \min{\left( x \right)}} $$

平均0、分散1に正規化(標準化)

Standardization。

平均を$\mu$、標準偏差を$\sigma$とする。

$$ x' = \frac{x - \mu}{\sigma} $$

標準偏差については$n$で割る母集団の標準偏差と$n−1$で割る標本標準偏差がある。ここで$n$はデータの個数。

母集団の標準偏差。

$$ \sigma^2=\frac{1}{n} \sum_{i=1}^{n} (x_i-\mu)^2 $$

標本標準偏差。

$$ u^2=\frac{1}{n-1} \sum_{i=1}^{n} (x_i-\overline{x})^2 $$

データを母集団全体と見なすか、母集団から抽出した標本と見なすかによって使い分けるが、以下で説明するライブラリや関数によってどちらの標準偏差が使われているが異なる。

データの個数$n$が十分大きければどちらでも結果に大差はないが、厳密に値を求めたい場合はどちらの標準偏差が使われているか注意が必要。

正規化・標準化を行うライブラリ

SciPyやscikit-learnでは正規化・標準化のための専用のクラスや関数が用意されている。

ここではPythonのリスト(list型)を例にそれぞれの使い方を説明する。NumPy配列numpy.ndarrayについてはリストと同様に処理可能だが、pandas.DataFrameに対しては若干処理が異なる。後述。

SciPyやscikit-learnを使わない方法についても後述する。

SciPy

SciPyには平均0、分散1に正規化(標準化)するscipy.stats.zscore()関数がある。最小値0、最大値1に正規化する関数はない。

引数にリストを指定すると標準化されたnumpy.ndarrayが返る。

import scipy.stats

l = [0, 1, 2, 3, 4]
print(l)
# [0, 1, 2, 3, 4]

print(scipy.stats.zscore(l))
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print(type(scipy.stats.zscore(l)))
# <class 'numpy.ndarray'>

デフォルトは引数ddof=0で$n$で割る標準偏差が使われるが、引数ddof=1とすると$n−1$で割る標準偏差が使われる。

print(scipy.stats.zscore(l, ddof=1))
# [-1.26491106 -0.63245553  0.          0.63245553  1.26491106]

リストのリスト(二次元配列)を指定すると、デフォルトでは列ごとに標準化される。

l_2d = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
print(l_2d)
# [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

print(scipy.stats.zscore(l_2d))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(scipy.stats.zscore(l_2d, ddof=1))
# [[-1. -1. -1.]
#  [ 0.  0.  0.]
#  [ 1.  1.  1.]]

引数axis=1とすると行ごとに標準化。

print(scipy.stats.zscore(l_2d, axis=1))
# [[-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]]

print(scipy.stats.zscore(l_2d, axis=1, ddof=1))
# [[-1.  0.  1.]
#  [-1.  0.  1.]
#  [-1.  0.  1.]]

引数axis=Noneとすると全体に対して標準化。

print(scipy.stats.zscore(l_2d, axis=None))
# [[-1.54919334 -1.161895   -0.77459667]
#  [-0.38729833  0.          0.38729833]
#  [ 0.77459667  1.161895    1.54919334]]

print(scipy.stats.zscore(l_2d, axis=None, ddof=1))
# [[-1.46059349 -1.09544512 -0.73029674]
#  [-0.36514837  0.          0.36514837]
#  [ 0.73029674  1.09544512  1.46059349]]

scikit-learn

scikit-learnでは、sklearn.preprocessingモジュールを使って正規化・標準化できる。

以下のリスト(一次元配列)、リストのリスト(二次元配列)を例とする。

from sklearn import preprocessing

l = [0, 1, 2, 3, 4]
print(l)
# [0, 1, 2, 3, 4]

l_2d = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
print(l_2d)
# [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

最小値0、最大値1に正規化

最小値0、最大値1に正規化するにはMinMaxScalerクラスを使う。

インスタンスを生成してからfit_transform()メソッドを使う。正規化されたnumpy.ndarrayが返る。

MinMaxScalerクラスでは一次元配列は処理されず、二次元配列のみが対象。列ごとに正規化され、行ごとや全体に対する処理はできない。

mm = preprocessing.MinMaxScaler()

# mm.fit_transform(l)
# ValueError: Expected 2D array, got 1D array instead:

l_2d_min_max = mm.fit_transform(l_2d)

print(l_2d_min_max)
# [[0.  0.  0. ]
#  [0.5 0.5 0.5]
#  [1.  1.  1. ]]

print(type(l_2d_min_max))
# <class 'numpy.ndarray'>

直接処理するminmax_scale()関数もある。

こちらは一次元配列も処理可能。また、二次元配列に対して引数axis=1とすると行ごとの処理となる。全体に対する処理はできない。

print(preprocessing.minmax_scale(l))
# [0.   0.25 0.5  0.75 1.  ]

print(preprocessing.minmax_scale(l_2d))
# [[0.  0.  0. ]
#  [0.5 0.5 0.5]
#  [1.  1.  1. ]]

print(preprocessing.minmax_scale(l_2d, axis=1))
# [[0.  0.5 1. ]
#  [0.  0.5 1. ]
#  [0.  0.5 1. ]]

平均0、分散1に正規化(標準化)

平均0、分散1に正規化(標準化)するにはStandardScalerクラスまたはscale()関数を使う。

使い方および制限は上述のMinMaxScalerクラス、minmax_scale()関数と同じ。

ss = preprocessing.StandardScaler()

# print(ss.fit_transform(l))
# ValueError: Expected 2D array, got 1D array instead:

l_2d_standardization = ss.fit_transform(l_2d)

print(l_2d_standardization)
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(type(l_2d_standardization))
# <class 'numpy.ndarray'>

print(preprocessing.scale(l))
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print(preprocessing.scale(l_2d))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(preprocessing.scale(l_2d, axis=1))
# [[-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]]

いずれの場合も$n$で割る標準偏差が使われる。$n−1$で割る標準偏差を使うことはできない。

Pythonのリスト(list型オブジェクト)の正規化・標準化

SciPy, scikit-learnを使った方法は上述の通り。

最小値、最大値は組み込み関数min(), max()で算出でき、Pythonの標準ライブラリのstatisticsモジュールを使うと平均や標準偏差も算出可能。

これらを利用すると正規化・標準化が可能。

以降のサンプルコードでは結果を見やすくするために標準ライブラリのpprintモジュール使っている。

一次元配列(リスト)に対する例。

リスト内包表記を使って各要素を処理している。

statistics.stdev()は$n−1$で割る標準偏差で、statistics.pstdev()は$n$で割る標準偏差。

import statistics
import pprint

l = [0, 1, 2, 3, 4]

print(l)
# [0, 1, 2, 3, 4]

def min_max(l):
    l_min = min(l)
    l_max = max(l)
    return [(i - l_min) / (l_max - l_min) for i in l]

print(min_max(l))
# [0.0, 0.25, 0.5, 0.75, 1.0]

def standardization(l):
    l_mean = statistics.mean(l)
    l_stdev = statistics.stdev(l)
    return [(i - l_mean) / l_stdev for i in l]

pprint.pprint(standardization(l))
# [-1.2649110640673518,
#  -0.6324555320336759,
#  0.0,
#  0.6324555320336759,
#  1.2649110640673518]

def standardization_p(l):
    l_mean = statistics.mean(l)
    l_pstdev = statistics.pstdev(l)
    return [(i - l_mean) / l_pstdev for i in l]

pprint.pprint(standardization_p(l))
# [-1.414213562373095,
#  -0.7071067811865475,
#  0.0,
#  0.7071067811865475,
#  1.414213562373095]

二次元配列(リストのリスト)に対する例。一応載せておくが、二次元配列を処理する場合は後述のNumPyを使ったほうが何かと簡単。

二次元配列(リストのリスト)の行ごとの処理。各リストに上述の一次元配列の処理を行っている。

l_2d = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

print(l_2d)
# [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

pprint.pprint([min_max(l_1d) for l_1d in l_2d], width=40)
# [[0.0, 0.5, 1.0],
#  [0.0, 0.5, 1.0],
#  [0.0, 0.5, 1.0]]

pprint.pprint([standardization(l_1d) for l_1d in l_2d], width=40)
# [[-1.0, 0.0, 1.0],
#  [-1.0, 0.0, 1.0],
#  [-1.0, 0.0, 1.0]]

pprint.pprint([standardization_p(l_1d) for l_1d in l_2d])
# [[-1.224744871391589, 0.0, 1.224744871391589],
#  [-1.224744871391589, 0.0, 1.224744871391589],
#  [-1.224744871391589, 0.0, 1.224744871391589]]

二次元配列(リストのリスト)の列ごとの処理。転置してから行ごとの処理を行い、再度転置してもとに戻す。

l_2d_min_max_col = list(zip(*[min_max(l_1d) for l_1d in list(zip(*l_2d))]))

pprint.pprint(l_2d_min_max_col, width=40)
# [(0.0, 0.0, 0.0),
#  (0.5, 0.5, 0.5),
#  (1.0, 1.0, 1.0)]

l_2d_standardization_col = list(zip(*[standardization(l_1d) for l_1d in list(zip(*l_2d))]))

pprint.pprint(l_2d_standardization_col, width=40)
# [(-1.0, -1.0, -1.0),
#  (0.0, 0.0, 0.0),
#  (1.0, 1.0, 1.0)]

l_2d_standardization_p_col = list(zip(*[standardization_p(l_1d) for l_1d in list(zip(*l_2d))]))

pprint.pprint(l_2d_standardization_p_col)
# [(-1.2247448713915892, -1.2247448713915892, -1.2247448713915892),
#  (0.0, 0.0, 0.0),
#  (1.2247448713915892, 1.2247448713915892, 1.2247448713915892)]

二次元配列(リストのリスト)の全体に対する処理。

sum(l_2d, [])で二次元配列を一次元配列に平坦化して全体の最大値や最小値、平均、標準偏差を算出し、リスト内包表記を繰り返し適用することですべての要素に対して処理を行っている。

def min_max_2d_all(l_2d):
    l_flatten = sum(l_2d, [])
    l_2d_min = min(l_flatten)
    l_2d_max = max(l_flatten)
    return [[(i - l_2d_min) / (l_2d_max - l_2d_min) for i in l_1d]
            for l_1d in l_2d]

pprint.pprint(min_max_2d_all(l_2d), width=40)
# [[0.0, 0.125, 0.25],
#  [0.375, 0.5, 0.625],
#  [0.75, 0.875, 1.0]]

def standardization_2d_all(l):
    l_flatten = sum(l_2d, [])
    l_2d_mean = statistics.mean(l_flatten)
    l_2d_stdev = statistics.stdev(l_flatten)
    return [[(i - l_2d_mean) / l_2d_stdev for i in l_1d]
            for l_1d in l_2d]

pprint.pprint(standardization_2d_all(l_2d))
# [[-1.4605934866804429, -1.0954451150103321, -0.7302967433402214],
#  [-0.3651483716701107, 0.0, 0.3651483716701107],
#  [0.7302967433402214, 1.0954451150103321, 1.4605934866804429]]

def standardization_p_2d_all(l):
    l_flatten = sum(l_2d, [])
    l_2d_mean = statistics.mean(l_flatten)
    l_2d_pstdev = statistics.pstdev(l_flatten)
    return [[(i - l_2d_mean) / l_2d_pstdev for i in l_1d]
            for l_1d in l_2d]

pprint.pprint(standardization_p_2d_all(l_2d))
# [[-1.5491933384829668, -1.161895003862225, -0.7745966692414834],
#  [-0.3872983346207417, 0.0, 0.3872983346207417],
#  [0.7745966692414834, 1.161895003862225, 1.5491933384829668]]

NumPy配列ndarrayの正規化・標準化

NumPyのメソッドを使う方法とSciPy, scikit-learnを使う方法を示す。SciPy, scikit-learnを使う方法は上述のリスト場合と同じだが若干注意が必要。

NumPyのメソッドを利用

NumPy配列numpy.ndarraymin(), max(), mean(), std()の各メソッドで最小値、最大値、平均、標準偏差を算出可能。引数axisによって配列全体、行ごと、列ごとの値を算出できる。デフォルトはaxis=Noneで配列全体。

std()はデフォルトでは引数ddof=0で$n$で割る標準偏差が使われるが、引数ddof=1とすると$n−1$で割る標準偏差が使われる。

一次元配列の例。同じmin()の処理が別々に行われているので、本来は次の二次元配列の例で示す関数のように先に一度だけ処理して結果を使い回すほうが効率的。

import numpy as np
import scipy.stats
from sklearn import preprocessing

a = np.array([0, 1, 2, 3, 4])
print(a)
# [0 1 2 3 4]

print((a - a.min()) / (a.max() - a.min()))
# [0.   0.25 0.5  0.75 1.  ]

print((a - a.mean()) / a.std())
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print((a - a.mean()) / a.std(ddof=1))
# [-1.26491106 -0.63245553  0.          0.63245553  1.26491106]

二次元配列の例。引数keepdims=Trueとすることで次元が保持されるのでそのまま加算減算が可能。二次元配列用の関数は一次元配列に対しても使える。

a_2d = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
print(a_2d)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

def min_max(x, axis=None):
    x_min = x.min(axis=axis, keepdims=True)
    x_max = x.max(axis=axis, keepdims=True)
    return (x - x_min) / (x_max - x_min)

print(min_max(a_2d))
# [[0.    0.125 0.25 ]
#  [0.375 0.5   0.625]
#  [0.75  0.875 1.   ]]

print(min_max(a_2d, axis=0))
# [[0.  0.  0. ]
#  [0.5 0.5 0.5]
#  [1.  1.  1. ]]

print(min_max(a_2d, axis=1))
# [[0.  0.5 1. ]
#  [0.  0.5 1. ]
#  [0.  0.5 1. ]]

print(min_max(a))
# [0.   0.25 0.5  0.75 1.  ]

def standardization(x, axis=None, ddof=0):
    x_mean = x.mean(axis=axis, keepdims=True)
    x_std = x.std(axis=axis, keepdims=True, ddof=ddof)
    return (x - x_mean) / x_std

print(standardization(a_2d))
# [[-1.54919334 -1.161895   -0.77459667]
#  [-0.38729833  0.          0.38729833]
#  [ 0.77459667  1.161895    1.54919334]]

print(standardization(a_2d, ddof=1))
# [[-1.46059349 -1.09544512 -0.73029674]
#  [-0.36514837  0.          0.36514837]
#  [ 0.73029674  1.09544512  1.46059349]]

print(standardization(a_2d, axis=0))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(standardization(a_2d, axis=0, ddof=1))
# [[-1. -1. -1.]
#  [ 0.  0.  0.]
#  [ 1.  1.  1.]]

print(standardization(a_2d, axis=1))
# [[-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]]

print(standardization(a_2d, axis=1, ddof=1))
# [[-1.  0.  1.]
#  [-1.  0.  1.]
#  [-1.  0.  1.]]

print(standardization(a))
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print(standardization(a, ddof=1))
# [-1.26491106 -0.63245553  0.          0.63245553  1.26491106]

SciPy, scikit-learnを利用

scipy.stats.zscore()の例。リストの場合と同じ。

print(scipy.stats.zscore(a))
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print(scipy.stats.zscore(a_2d))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(scipy.stats.zscore(a_2d, axis=None, ddof=1))
# [[-1.46059349 -1.09544512 -0.73029674]
#  [-0.36514837  0.          0.36514837]
#  [ 0.73029674  1.09544512  1.46059349]]

sklearn.preprocessingの例。整数intの配列を処理すると以下のように、浮動小数点floatに変換しましたという警告が出る。

DataConversionWarning: Data with input dtype int64 was converted to float64 by MinMaxScaler.

astype()で型変換を行う。

mm = preprocessing.MinMaxScaler()

print(mm.fit_transform(a_2d.astype(float)))
# [[0.  0.  0. ]
#  [0.5 0.5 0.5]
#  [1.  1.  1. ]]

print(preprocessing.minmax_scale(a.astype(float)))
# [0.   0.25 0.5  0.75 1.  ]

print(preprocessing.minmax_scale(a_2d.astype(float), axis=1))
# [[0.  0.5 1. ]
#  [0.  0.5 1. ]
#  [0.  0.5 1. ]]

ss = preprocessing.StandardScaler()

print(ss.fit_transform(a_2d.astype(float)))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(preprocessing.scale(a.astype(float)))
# [-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

print(preprocessing.scale(a_2d.astype(float), axis=1))
# [[-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]
#  [-1.22474487  0.          1.22474487]]

pandas.DataFrame, pandas.Seriesの正規化・標準化

pandasのメソッドを使う方法とSciPy, scikit-learnを使う方法を示す。

pandasのメソッドを利用

pandas.DataFrame, pandas.Seriesも、min(), max(), mean(), std()の各メソッドで最小値、最大値、平均、標準偏差を算出可能。

行ごとの処理は以下の例では.Tで転置してから列ごとに処理して再度転置してもとに戻している。実際はpandas.DataFrameを行ごとに正規化・標準化することはほとんどない。

全体に対する値はvalues属性でnumpy.ndarrayを取得して各メソッドを適用すれば算出できる。

pandas.DataFrame, pandas.Seriesstd()メソッドは引数ddof=1がデフォルト。numpy.ndarraystd()メソッド(ddof=0がデフォルト)と異なるので注意。

なお、数値以外の列が含まれている場合は数値列のみを抽出してから処理を行う。以下の記事を参照。

pandas.DataFrameの例。

最小値0、最大値1に正規化。同じmin()の処理が別々に行われているので、本来はNumPyの二次元配列の例のように先に一度だけ処理して結果を使い回すほうが効率的。

import pandas as pd
import scipy.stats
from sklearn import preprocessing

df = pd.DataFrame([[0, 1, 2], [3, 4, 5], [6, 7, 8]],
                  columns=['col1', 'col2', 'col3'],
                  index=['a', 'b', 'c'])

print(df)
#    col1  col2  col3
# a     0     1     2
# b     3     4     5
# c     6     7     8

print((df - df.min()) / (df.max() - df.min()))
#    col1  col2  col3
# a   0.0   0.0   0.0
# b   0.5   0.5   0.5
# c   1.0   1.0   1.0

print(((df.T - df.T.min()) / (df.T.max() - df.T.min())).T)
#    col1  col2  col3
# a   0.0   0.5   1.0
# b   0.0   0.5   1.0
# c   0.0   0.5   1.0

print((df - df.values.min()) / (df.values.max() - df.values.min()))
#     col1   col2   col3
# a  0.000  0.125  0.250
# b  0.375  0.500  0.625
# c  0.750  0.875  1.000

平均0、分散1に正規化(標準化)。上述のようにpandas.DataFramestd()メソッドと.valuesで取得できるnumpy.ndarraystd()メソッドの引数ddofのデフォルト値が異なるので注意。デフォルト値であっても明示的に指定したほうが安心かもしれない。

print((df - df.mean()) / df.std())
#    col1  col2  col3
# a  -1.0  -1.0  -1.0
# b   0.0   0.0   0.0
# c   1.0   1.0   1.0

print((df - df.mean()) / df.std(ddof=0))
#        col1      col2      col3
# a -1.224745 -1.224745 -1.224745
# b  0.000000  0.000000  0.000000
# c  1.224745  1.224745  1.224745

print(((df.T - df.T.mean()) / df.T.std()).T)
#    col1  col2  col3
# a  -1.0   0.0   1.0
# b  -1.0   0.0   1.0
# c  -1.0   0.0   1.0

print(((df.T - df.T.mean()) / df.T.std(ddof=0)).T)
#        col1  col2      col3
# a -1.224745   0.0  1.224745
# b -1.224745   0.0  1.224745
# c -1.224745   0.0  1.224745

print((df - df.values.mean()) / df.values.std())
#        col1      col2      col3
# a -1.549193 -1.161895 -0.774597
# b -0.387298  0.000000  0.387298
# c  0.774597  1.161895  1.549193

print((df - df.values.mean()) / df.values.std(ddof=1))
#        col1      col2      col3
# a -1.460593 -1.095445 -0.730297
# b -0.365148  0.000000  0.365148
# c  0.730297  1.095445  1.460593

pandas.Seriesの例。便宜上、元のpandas.DataFrameをコピーして使っている。

pandas.DataFrameと同様に処理できる。

df_ = df.copy()
s = df_['col1']
df_['col1_min_max'] = (s - s.min()) / (s.max() - s.min())
df_['col1_standardization'] = (s - s.mean()) / s.std()

print(df_)
#    col1  col2  col3  col1_min_max  col1_standardization
# a     0     1     2           0.0                  -1.0
# b     3     4     5           0.5                   0.0
# c     6     7     8           1.0                   1.0

新たな列を加える方法の詳細は以下の記事を参照。

Scipy, scikit-learnを利用

scipy.stats.zscore()の例。

scipy.stats.zscore()の引数にpandas.DataFrameを指定すると、標準化された結果がnumpy.ndarrayとして返される。引数axis, ddofの使い方は上述の通り。

print(scipy.stats.zscore(df))
# [[-1.22474487 -1.22474487 -1.22474487]
#  [ 0.          0.          0.        ]
#  [ 1.22474487  1.22474487  1.22474487]]

print(type(scipy.stats.zscore(df)))
# <class 'numpy.ndarray'>

print(scipy.stats.zscore(df, axis=None, ddof=1))
# [[-1.46059349 -1.09544512 -0.73029674]
#  [-0.36514837  0.          0.36514837]
#  [ 0.73029674  1.09544512  1.46059349]]

コンストラクタpandas.DataFrameの第一引数dataに処理されたnumpy.ndarrayindexcolumnsに元のindexcolumnsを指定すれば、値が標準化されたpandas.DataFrameが得られる。

df_standardization = pd.DataFrame(scipy.stats.zscore(df),
                                  index=df.index, columns=df.columns)

print(df_standardization)
#        col1      col2      col3
# a -1.224745 -1.224745 -1.224745
# b  0.000000  0.000000  0.000000
# c  1.224745  1.224745  1.224745

pandas.Seriesに対しても同様だが、pandas.DataFrameの列として追加する場合はnumpy.ndarrayをそのまま使える。

df_ = df.copy()
df_['col1_standardization'] = scipy.stats.zscore(df_['col1'])
print(df_)
#    col1  col2  col3  col1_standardization
# a     0     1     2             -1.224745
# b     3     4     5              0.000000
# c     6     7     8              1.224745

sklearn.preprocessingの例。

こちらもscipy.stats.zscore()と同様にpandas.DataFrameを引数に指定すると、結果がnumpy.ndarrayとして返される。

mm = preprocessing.MinMaxScaler()

print(mm.fit_transform(df))
# [[0.  0.  0. ]
#  [0.5 0.5 0.5]
#  [1.  1.  1. ]]

print(type(mm.fit_transform(df)))
# <class 'numpy.ndarray'>

print(preprocessing.minmax_scale(df))
# [[0.  0.  0. ]
#  [0.5 0.5 0.5]
#  [1.  1.  1. ]]

print(type(preprocessing.minmax_scale(df)))
# <class 'numpy.ndarray'>

df_min_max = pd.DataFrame(mm.fit_transform(df),
                          index=df.index, columns=df.columns)

print(df_min_max)
#    col1  col2  col3
# a   0.0   0.0   0.0
# b   0.5   0.5   0.5
# c   1.0   1.0   1.0

df_ = df.copy()
s = df_['col1'].astype(float)
df_['col1_min_max'] = preprocessing.minmax_scale(s)
df_['col1_standardization'] = preprocessing.scale(s)

print(df_)
#    col1  col2  col3  col1_min_max  col1_standardization
# a     0     1     2           0.0             -1.224745
# b     3     4     5           0.5              0.000000
# c     6     7     8           1.0              1.224745
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事