プロジェクト — データクレンジング

1. プロジェクト:NumPy を使ったデータクレンジング

(1) シナリオ

あなたはデータアナリストです。10,000行分のセンサーデータが記録されたCSVファイルを受け取りましたが、そのデータは乱雑な状態です。欠損値、外れ値、単位の不統一、重複行などが含まれています。

(2) タスク

1. 積み込みと点検

PYTHON
import numpy as np

# Load data (simulated)
rng = np.random.default_rng(42)
n = 10000

# Generate clean data
temperature = rng.normal(25, 5, n)  # mean 25°C, std 5°C
humidity = rng.uniform(30, 80, n)    # 30-80%
pressure = rng.normal(1013, 10, n)   # mean 1013 hPa

# Add some NaN values
temperature[0:50] = np.nan
humidity[200:250] = np.nan

# Add outliers
temperature[1000:1010] = 100  # impossible temperature
pressure[2000:2005] = 0       # impossible pressure

# Stack into structured array
data = np.column_stack([temperature, humidity, pressure])
print(f"Shape: {data.shape}")
print(f"NaN count: {np.sum(np.isnan(data), axis=0)}")

2. 欠損値の処理

PYTHON
# Replace NaN with column mean
col_mean = np.nanmean(data, axis=0)
data_clean = np.where(np.isnan(data), col_mean, data)

3. 外れ値の除去(IQR法)

PYTHON
# IQR-based outlier removal
Q1 = np.percentile(data_clean, 25, axis=0)
Q3 = np.percentile(data_clean, 75, axis=0)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR

# Filter rows that are within bounds for all columns
mask = np.all((data_clean >= lower) & (data_clean <= upper), axis=1)
data_filtered = data_clean[mask]
print(f"Rows before: {len(data_clean)}, after: {len(data_filtered)}")

4. 列の正規化(Zスコア)

PYTHON
mean = data_filtered.mean(axis=0)
std = data_filtered.std(axis=0)
data_normalized = (data_filtered - mean) / std
print(f"Normalized mean: {data_normalized.mean(axis=0).round(6)}")
print(f"Normalized std:  {data_normalized.std(axis=0).round(6)}")

5. クリーンなデータのエクスポート

PYTHON
# Save cleaned data
np.save('sensor_data_clean.npy', data_filtered)
np.savetxt('sensor_data_clean.csv', data_filtered, delimiter=',',
           header='temperature,humidity,pressure', comments='')
print("Clean data exported.")

(1) ▶ サンプル:データの読み込みと確認(難易度 ⭐)

PYTHON
import numpy as np

rng = np.random.default_rng(42)
data = rng.normal(25, 5, size=(1000, 3))
print("Shape:", data.shape)
print("First 5 rows:\n", data[:5])
print("NaN count:", np.sum(np.isnan(data)))
print("Mean:", data.mean(axis=0))
print("Std:", data.std(axis=0))

出力:

TEXT
形状: (1000, 3)
最初の5行:
 [[28.698 20.884 28.847]
 [24.899 25.891 29.574]
 [27.198 28.793 25.009]
 [24.694 25.771 25.929]
 [26.676 25.174 23.938]]
NaN の個数: 0
平均:[25.045 24.908 25.039]
標準値:[5.019 5.045 5.030]

(2) ▶ サンプル:np.where を使った欠損値の処理(難易度 ⭐⭐)

PYTHON
import numpy as np

data = np.array([1.0, 2.0, np.nan, 4.0, np.nan, 6.0, 7.0])

# Replace NaN with column mean
col_mean = np.nanmean(data)
clean = np.where(np.isnan(data), col_mean, data)
print("Original:", data)
print("Cleaned:", clean)
print("Mean after:", clean.mean())

出力:

TEXT
原文:[ 1.  2. なし  4. なし  6.  7.]
整理済み:[1.  2.  4.  4.  4.  6.  7.]
変更後の平均:4.0

(3) ▶ サンプル:IQR を用いた外れ値の除去(難易度 ⭐⭐)

PYTHON
import numpy as np

rng = np.random.default_rng(42)
data = np.concatenate([rng.normal(50, 10, 95), [200, -50, 300, -80, 150]])

Q1 = np.percentile(data, 25)
Q3 = np.percentile(data, 75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR

filtered = data[(data >= lower) & (data <= upper)]
print(f"Total: {len(data)}, Outliers: {len(data) - len(filtered)}")
print(f"Before: mean={data.mean():.1f}, After: mean={filtered.mean():.1f}")

出力:

TEXT
合計:100、外れ値:5
実施前:平均=56.8、実施後:平均=49.1


❓ よくある質問

Q データに文字列の列が含まれている場合はどうすればよいですか?
A NumPyのloadtxt関数は、異なるデータ型の混在したデータを処理できません。データ型が混在している場合は、np.genfromtxtdtype=Noneを組み合わせて使用するか、複雑なCSVファイルの場合はPandasを使用してください。
Q どのIQR倍率を使えばよいか、どうすればわかりますか?
A 「軽度の」外れ値には1.5が、 「極端な」外れ値には3.0が標準的に用いられます。 これらは標準正規分布に基づくもので、1.5×IQR ≈ ±2.7σ となります。
Q 外れ値を除去する前と後、どちらで正規化すべきですか?
A 後です。外れ値は平均値や標準偏差を歪めるため、正規化の効果が低下してしまいます。必ずまずデータをクリーニングしてから、正規化を行ってください。

📖 まとめ

このプロジェクトでは、以下のことを実践しました:


📝 練習問題

  1. 初心者向け(難易度 ⭐):IQRの乗数を3.0に変更してください。検出される外れ値はいくつ減りますか?

  2. 中級(難易度 ⭐⭐):「timestamp」という列を追加し、営業時間外(午前9時~午後5時)のデータを除外してください。

  3. 上級(難易度 ⭐⭐⭐):外れ値検出のために移動ウィンドウを実装する。各点の局所的な近傍(周囲の100点)の四分位範囲(IQR)の外側にある場合にのみ、その点を外れ値としてフラグを立てる。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%