生センサーデータ はギザギザでノイズだらけ。そのままグラフにすると「結局何が起きたか」が見えにくい。本記事では Python の pandas / numpy で書ける、シンプルだが効果的なノイズ処理を紹介します。
1. ノイズの正体
- ホワイトノイズ: 完全ランダムな揺らぎ、+0.1 +0.05 -0.2 のような
- スパイク: 一瞬だけ異常値 (電源ノイズ・通信エラー)
- ドリフト: ゆっくり値がずれていく (温度依存・経年劣化)
- 量子化誤差: センサーの分解能による「カクカク」した変化
2. 移動平均 (Moving Average)
pandas で移動平均
Python
import pandas as pddf = pd.read_csv('temperature.csv')df['time'] = pd.to_datetime(df['timestamp'], unit='s')df = df.set_index('time')
# 5 分の移動平均 (1 分間隔データなら window=5)df['temp_ma5'] = df['temp'].rolling(window=5).mean()
# 30 分の移動平均df['temp_ma30'] = df['temp'].rolling(window=30).mean()
# 比較プロットimport matplotlib.pyplot as pltfig, ax = plt.subplots(figsize=(10, 5))ax.plot(df.index, df['temp'], 'k-', alpha=0.3, label='生データ')ax.plot(df.index, df['temp_ma5'], 'b-', label='5 分移動平均')ax.plot(df.index, df['temp_ma30'], 'r-', label='30 分移動平均')ax.legend()plt.savefig('moving_average.png', dpi=200)3. 外れ値の検出と除去 (3σ ルール)
3σ で外れ値をマスク
Python
import numpy as np
mean = df['temp'].mean()std = df['temp'].std()
# 3σ を超えるものを外れ値として NaN にdf['temp_clean'] = df['temp'].where( (df['temp'] > mean - 3*std) & (df['temp'] < mean + 3*std))
# 線形補間で埋めるdf['temp_clean'] = df['temp_clean'].interpolate(method='linear')
print(f'生データ: 平均 {mean:.2f}, σ {std:.2f}')print(f'除去された外れ値: {df["temp"].isna().sum()} 件')4. メディアンフィルタ (スパイク除去に強い)
「ある時刻の値を、前後 N 個の中央値に置き換える」フィルタ。1 点だけ大きく外れたスパイクを綺麗に除けます。
5 点メディアンフィルタ
Python
df['temp_median'] = df['temp'].rolling(window=5, center=True).median()5. 比較表:いつ何を使う?
| 処理 | 向く場面 | 弱点 |
|---|---|---|
| 移動平均 | ホワイトノイズの平滑化 | 急変動も鈍化させてしまう |
| メディアンフィルタ | スパイク (一瞬の異常値) 除去 | 本物の急変動も丸める可能性 |
| 3σ 外れ値除去 | 明らかな故障値の除外 | サンプル数が少ないと判定が不安定 |
| 指数移動平均 (EMA) | リアルタイム処理向き | パラメータ調整が必要 |
| ローパスフィルタ | 高周波ノイズの完全除去 | 実装やや高度 |
6. データから「物語」を引き出す
ノイズ処理の本質
「綺麗にすること」が目的ではなく、「言いたい結論を支える」ためにノイズを除く。生データの上に、移動平均と外れ値除去を 重ねて表示 すると、「どこを根拠に結論を言っているか」が読み手にも伝わります。
7. 次の話
EP.10 では クラウドにデータを送る 方法を扱います。Google Sheets / ThingSpeak への送信で、家にいなくてもスマホからグラフが見られる仕組みを作ります。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。