![見出し画像](https://assets.st-note.com/production/uploads/images/152616201/rectangle_large_type_2_e05b5b31f6fb7a871fb94938c928c869.png?width=1200)
制作物#3 CSVの外れ値探索
1.概要
本システムは、指定されたCSVファイル内の数値データに対して複数の外れ値検出方法を適用し、検出された外れ値の情報をCSVファイルに保存する。また、各外れ値検出方法の結果を視覚化し、結果の分析を容易にすることを目的としています。
2.使用言語
Python
3.使用ライブラリ
pandas:データフレームの操作
numpy:数値計算
matplotlib:データの可視化
scipy:統計計算
sklearn.ensemble.IsolationForest:Isolation Forestによる外れ値検出
sklearn.neighbors.LocalOutlierFactor:LOF(Local Outlier Factor)による外れ値検出
4.機能概要
CSVファイルの読み込み
CSVファイルからデータを読み込み、指定されたカラムに対して外れ値検出を行います。
読み込むファイルはユーザーが指定します。
外れ値検出
指定された複数のカラムに対して、以下の外れ値検出方法を適用します。
IQR方式:四分位範囲を用いた方法
Zスコア方式:標準偏差を基にした方法
MAD方式:中央値からの偏差を用いた方法
Isolation Forest方式:機械学習アルゴリズムを用いた方法
LOF方式:局所的な密度に基づく方法
データの可視化
各外れ値検出方法に基づいて、以下の形式でデータを可視化します。
IQR方式:箱ひげ図
Zスコア方式:散布図
MAD方式:散布図
Isolation Forest方式:散布図
LOF方式:散布図
可視化は、異常値の分布を理解しやすくするために色分けが行われます。
外れ値結果の保存
各カラムに対する外れ値検出の結果をCSVファイルとして保存します。
出力ファイルには、データのNo、データ収集日、検出された外れ値の値、使用した検出方法が含まれます。
保存場所とファイル名はユーザーが指定します。
5.入力
CSVファイル
外れ値を検出したいデータが格納されたCSVファイル。
ファイル内の各カラムに数値データが含まれている必要があります。
ターゲットカラム
外れ値を検出したいカラム名をリスト形式で指定します。
6.出力
外れ値検出結果
各ターゲットカラムに対して外れ値検出結果をCSVファイルに保存します。
ファイル名は次の形式で指定されます:outliers_detection_results_カラム名.csv
可視化グラフ
外れ値検出結果に基づく各検出方法のグラフが生成され、画面に表示されます。
7.エラー処理
数値データ以外のカラム指定エラー
数値データではないカラムを指定した場合、該当するカラムに対して処理が行われず、次のカラムに進むように設計されています。
ファイル読み込みエラー
指定されたファイルが存在しない場合や、読み込みに失敗した場合、エラーメッセージを表示し処理を停止します。
8.要求されるシステム要件
Python 3.8以上
pandas, numpy, matplotlib, scipy, sklearnの各ライブラリがインストールされていること
9.コード
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
from sklearn.ensemble import IsolationForest
from sklearn.neighbors import LocalOutlierFactor
# 1. CSVファイルを読み込みます
df = pd.read_csv('外れ値を算出したいCSVファイル.csv')
# 2. 外れ値を検出するカラムを指定します(複数可)
target_columns = ['Colum1', 'Colum2', 'Colum3'] # ここに検出したいカラム名を指定してください
for target_column in target_columns:
# 3. 出力用のリストを初期化します
outliers_list = []
# 4. 指定したカラムに対して外れ値検出を行います
if pd.api.types.is_numeric_dtype(df[target_column]): # 数値データのみ処理
# 4-1. IQR方式
# IQRを計算し、1.5倍の範囲外のデータポイントを外れ値として検出
Q1 = df[target_column].quantile(0.25) # 第1四分位数(25パーセンタイル)
Q3 = df[target_column].quantile(0.75) # 第3四分位数(75パーセンタイル)
IQR = Q3 - Q1 # IQR(Interquartile Range)の計算
lower_bound = Q1 - 1.5 * IQR # 外れ値の下限
upper_bound = Q3 + 1.5 * IQR #外れ値の上限
iqr_outliers = df[(df[target_column] < lower_bound) | (df[target_column] > upper_bound)]
for idx in iqr_outliers.index:
outliers_list.append([df.loc[idx, 'No'], df.loc[idx, 'Data collection date'], df.loc[idx, target_column], 'IQR'])
# 4-2. Zスコア方式 (Z-Score)
# 各データポイントのZスコアを計算し、絶対値が3を超えるデータポイントを外れ値として検出します。
z_scores = np.abs(stats.zscore(df[target_column].dropna())) # Zスコアの計算
z_scores = pd.Series(z_scores, index=df[target_column].dropna().index) # インデックスを保持してZスコアをシリーズ化
zscore_outliers = df[target_column][df[target_column].index.isin(z_scores[z_scores > 3].index)] # Zスコアが3を超えるデータを外れ値として抽出
zscore_colors = pd.Series(0.0, index=df.index) # カラーマッピング用のシリーズをfloat64で初期化
zscore_colors.loc[z_scores.index] = (z_scores > 3).astype(float) # Zスコアが3を超える箇所を色分け
for idx in zscore_outliers.index:
outliers_list.append([df.loc[idx, 'No'], df.loc[idx, 'Data collection date'], df.loc[idx, target_column], 'Z-Score'])
# 4-3. MAD方式
# 中央値からの偏差の絶対値の中央値(MAD)を使用して外れ値を検出します。
median = df[target_column].median() # 中央値の計算
mad = np.median(np.abs(df[target_column] - median)) # 中央絶対偏差(MAD)の計算
if mad == 0: # MADが0の場合、非常に小さい値を設定
mad = np.finfo(float).eps
modified_z_scores = 0.6745 * (df[target_column] - median) / mad # 修正Zスコアの計算
mad_outliers = df[target_column][np.abs(modified_z_scores) > 3.5] # 修正Zスコアが3.5を超えるデータを外れ値として検出
for idx in mad_outliers.index:
outliers_list.append([df.loc[idx, 'No'], df.loc[idx, 'Data collection date'], df.loc[idx, target_column], 'MAD'])
# 4-4. Isolation Forest方式
# 木を用いた機械学習アルゴリズムであるIsolation Forestを使って外れ値を検出します。
iso_forest = IsolationForest(contamination=0.05) # Isolation Forestモデルのインスタンス化、汚染率0.05
df_subset = df[[target_column]].dropna() # 欠損値を除いたサブセットを作成
anomaly_iso = iso_forest.fit_predict(df_subset) # モデルの適用と異常値の検出
df['anomaly_iso'] = np.nan # 新しいカラムを初期化
df.loc[df_subset.index, 'anomaly_iso'] = anomaly_iso # 検出結果を元のデータフレームに配置
iso_forest_outliers = df[df['anomaly_iso'] == -1][target_column] # 異常値として検出されたデータを抽出
for idx in iso_forest_outliers.index:
outliers_list.append([df.loc[idx, 'No'], df.loc[idx, 'Data collection date'], df.loc[idx, target_column], 'Isolation Forest'])
# 4-5. LOF方式
# 各データポイントが属する局所的な密度に基づいて外れ値を検出します。
lof = LocalOutlierFactor(n_neighbors=20) # LOFモデルのインスタンス化、近傍数20
anomaly_lof = lof.fit_predict(df_subset) # モデルの適用と異常値の検出
df['anomaly_lof'] = np.nan # 新しいカラムを初期化
df.loc[df_subset.index, 'anomaly_lof'] = anomaly_lof # 検出結果を元のデータフレームに配置
lof_outliers = df[df['anomaly_lof'] == -1][target_column] # 異常値として検出されたデータを抽出
for idx in lof_outliers.index:
outliers_list.append([df.loc[idx, 'No'], df.loc[idx, 'Data collection date'], df.loc[idx, target_column], 'LOF'])
# 5. データのプロット設定
plt.figure(figsize=(14, 10))
# 6. データの可視化
# 6-1. IQR方式 - 箱ひげ図
plt.subplot(3, 2, 1)
plt.boxplot(df[target_column].dropna())
plt.title(f'IQR - Box Plot ({target_column})')
plt.xlabel(target_column)
plt.ylabel('Values')
# 6-2. Zスコア方式 - 散布図
plt.subplot(3, 2, 2)
plt.scatter(df.index, df[target_column], c=zscore_colors, cmap='coolwarm', edgecolors='k')
plt.title(f'Z-Score - Scatter Plot ({target_column})')
plt.xlabel('Index')
plt.ylabel(target_column)
# 6-3. MAD方式 - 散布図
median = df[target_column].median()
mad = np.median(np.abs(df[target_column] - median))
modified_z_scores = 0.6745 * (df[target_column] - median) / mad
mad_colors = pd.Series(0.0, index=df.index) # float64で初期化
mad_colors.loc[df.index] = (np.abs(modified_z_scores) > 3.5).astype(float)
plt.subplot(3, 2, 3)
plt.scatter(df.index, df[target_column], c=mad_colors, cmap='coolwarm', edgecolors='k')
plt.title(f'MAD - Scatter Plot ({target_column})')
plt.xlabel('Index')
plt.ylabel(target_column)
# 6-4. Isolation Forest方式 - 散布図
plt.subplot(3, 2, 4)
plt.scatter(df.index, df[target_column], c=(df['anomaly_iso'] == -1).astype(float), cmap='coolwarm', edgecolors='k')
plt.title(f'Isolation Forest - Scatter Plot ({target_column})')
plt.xlabel('Index')
plt.ylabel(target_column)
# 6-5. LOF方式 - 散布図
plt.subplot(3, 2, 5)
plt.scatter(df.index, df[target_column], c=(df['anomaly_lof'] == -1).astype(float), cmap='coolwarm', edgecolors='k')
plt.title(f'LOF - Scatter Plot ({target_column})')
plt.xlabel('Index')
plt.ylabel(target_column)
plt.tight_layout()
plt.show()
# 7. 外れ値の結果をCSVに書き出します
outliers_df = pd.DataFrame(outliers_list, columns=['No', 'Data collection date', target_column, 'Outlier Reason'])
output_file = f'格納先フォルダー名/X.外れ値/outliers_detection_results_{target_column}.csv' #保存先とファイル名を指定
outliers_df.to_csv(output_file, index=False)
print(f"外れ値の結果が保存されました: {output_file}")