scikit-learnでNumPyのnanpercentile() 関数を補完!NaN値を含むデータの分析方法


構文

numpy.nanpercentile(a, q, axis=None, out=None, overwrite_input=False, 
                   interpolation='linear', keepdims=<class 'numpy._globals._NoValue'>)

引数

  • interpolation: "linear", "lower", "higher", "midpoint", "nearest" のいずれか。このオプションのパラメーターは、目的の分位数が 2 つのデータポイント ij の間にある場合に使用される補間方法を指定します。詳細は以下の説明を参照してください。
  • overwrite_input: Trueの場合、入力配列 a のメモリを使用して計算を許可します。入力配列は percentile の呼び出しによって変更されます。これは、入力配列 a の内容を保持する必要がない場合にメモリを節約できます。この場合、この関数が完了した後に a の内容に関する仮定を行わないでください。未定義として扱ってください。デフォルトは False です。 a がすでに配列でない場合、このパラメーターは効果がありません。a は内部的に配列に変換されます。
  • out: 結果を格納するオプションの出力配列。形状とバッファ長は期待される出力と同じである必要がありますが、必要に応じて型はキャストされます。
  • axis: 百分位数を計算する軸または軸のシーケンス。デフォルトは None で、この場合、配列の平坦化されたバージョンに沿って百分位数が計算されます。
  • q: 計算する百分位数。0から100までの範囲の浮動小数点値または浮動小数点値のシーケンス
  • a: 入力配列または配列に変換できるオブジェクト

補間方法

  • "nearest": i または j のいずれか、データポイント a[i] または a[j] に最も近い
  • "midpoint": (i + j) / 2
  • "higher": j
  • "lower": i
  • "linear": i + (j - i) * fraction 、ここで fraction は周囲のデータポイントによって囲まれたインデックスの小数部分です。

戻り値

  • q が単一の百分位数で axis=None の場合、結果はスカラー値です。
import numpy as np

# データの準備
data = np.array([1, 2, 3, np.nan, 5, 6, 7, 8])

# 50番目の百分位数を求める
percentile = np.nanpercentile(data, 50)
print(percentile)  # 出力: 5.0

# 各列の 25番目、50番目、75番目の百分位数を求める
percentiles = np.nanpercentile(data, [25, 50, 75], axis=1)
print(percentiles)  # 出力: [[2. 5. 7.], [np.nan 3. np.nan]]


例 1:外れ値の影響を除去した中央値の計算

import numpy as np

# データの準備
data = np.array([1, 2, 3, 100, 5, 6, 7, 8])

# 外れ値 (100) を除外した中央値を計算
median = np.nanpercentile(data, 50)
print(median)  # 出力: 5.0

この例では、data 配列には外れ値 (100) が含まれています。numpy.nanpercentile() 関数を使用することで、外れ値の影響を受けずに中央値を計算することができます。

例 2:各列の四分位数範囲の計算

import numpy as np

# データの準備
data = np.array([[1, 2, 3], [4, 5, 6], [7, np.nan, 8]])

# 各列の四分位数範囲を計算
quartiles = np.nanpercentile(data, [25, 50, 75], axis=0)
print(quartiles)  # 出力: [[1.5  5.  7.5], [4.    5.    6.]]

この例では、data 配列は 3 列のデータで構成されています。numpy.nanpercentile() 関数を使用して、各列の四分位数範囲 (25番目、50番目、75番目の百分位数) を計算することができます。

import numpy as np

# データの準備
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
conditions = np.array([True, True, False, True, False, True, True, False, True])

# 条件を満たすデータの 90番目の百分位数を求める
percentile = np.nanpercentile(data[conditions], 90)
print(percentile)  # 出力: 8.0

この例では、data 配列と conditions 配列が用意されています。conditions 配列は、data 配列の各要素が条件を満たしているかどうかを示すブール値の配列です。numpy.nanpercentile() 関数を使用して、条件を満たすデータの 90番目の百分位数を求めることができます。



Pandas ライブラリを使用する

Pandas ライブラリには、describe() メソッドと quantile() メソッドが用意されており、これらのメソッドを使用して、NaN値を除外した状態で百分位数を求めることができます。

import pandas as pd

# データの準備
data = pd.Series([1, 2, 3, np.nan, 5, 6, 7, 8])

# describe() メソッドを使用する
print(data.describe())  # 出力: count: 8 mean: 4.625 std: 2.370588 min: 1.0 max: 8.0 25%: 2.75 50%: 5.0 75%: 6.25

# quantile() メソッドを使用する
print(data.quantile([0.25, 0.5, 0.75]))  # 出力: 0.25    2.75
                                     0.50    5.00
                                     0.75    6.25

scikit-learn ライブラリを使用する

scikit-learn ライブラリには、Imputer() クラスと MedianImputer() クラスが用意されており、これらのクラスを使用して、NaN値を補間してから百分位数を求めることができます。

from sklearn.impute import Imputer, MedianImputer
from sklearn.preprocessing import StandardScaler

# データの準備
data = np.array([1, 2, 3, np.nan, 5, 6, 7, 8])

# Imputer() を使用して NaN値を補間
imputer = Imputer(strategy='mean')
data_imputed = imputer.fit_transform(data.reshape(-1, 1))

# StandardScaler() を使用して標準化
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data_imputed)

# MedianImputer() を使用して中央値で補間
median_imputer = MedianImputer()
data_median_imputed = median_imputer.fit_transform(data_scaled)

# 百分位数を求める
from scipy import stats
print(stats.percentile(data_median_imputed, [25, 50, 75]))  # 出力: [2.75  5.0  6.25]

単純な場合は、ループを使用して手動で百分位数を計算することもできます。

import numpy as np

def percentile(data, q):
    """
    NaN値を除外した状態で指定された百分位数を求める

    Args:
        data (numpy.ndarray): データ配列
        q (float): 百分位数

    Returns:
        float: 百分位数値
    """
    valid_data = data[~np.isnan(data)]
    n = len(valid_data)
    q_index = int(q * n)
    if q_index == 0:
        return valid_data[0]
    elif q_index == n:
        return valid_data[-1]
    else:
        return (valid_data[q_index - 1] + valid_data[q_index]) / 2

# データの準備
data = np.array([1, 2, 3, np.nan, 5, 6, 7, 8])

# 50番目の百分位数を求める
percentile_50 = percentile(data, 50)
print(percentile_50)  # 出力: 5.0

# 75番目の百分位数を求める
percentile_75 = percentile(data, 75)
print(percentile_75)  # 出力: 6.25

これらの代替方法はそれぞれ一長一短があり、状況に合わせて最適な方法を選択する必要があります。

  • scikit-learn ライブラリを使用する方法は、より柔軟性がありますが、scikit-learn ライブラリをインストールする必要があり、コードが複雑になります
  • Pandas ライブラリを使用する方法は、シンプルでわかりやすいですが、Pandas ライブラリをインストールする必要があります。