まとめ
- まずは CSV を読み込み、列型や欠損・重複を確認し、分析に耐える状態かを点検します。
- 日付列は
datetimeに変換し、Dateをインデックスに設定しておくと後続処理が楽になります。 - トレンド・季節性・分布・自己相関を可視化し、定常性テスト(ADF)で系列の性質を把握します。
- 3 次多項式でトレンド線を描く関数を用意しておくと、後で差分や除去操作を検討しやすくなります。
1. 使用ライブラリ #
実験で使う標準ライブラリ/サードパーティをまとめて import しておきます。
import datetime
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from scipy import stats
from statsmodels.tsa import stattools
2. データを読み込む #
最初の 10 行を表示し、列名や桁数を把握しておきます。Date と Temp の 2 列のみというシンプルな構成です。
data = pd.read_csv("sample.csv")
data.head(10)
3. 日付列を datetime 型に変換する
#
object のままでは並べ替えや差分計算が面倒なので、datetime.datetime.strptime で日付に変換します。
data["Date"] = data["Date"].apply(
lambda x: datetime.datetime.strptime(str(x), "%Y-%m-%d")
)
print(f"Date列の dtype: {data['Date'].dtype}")
4. 基本統計・欠損・重複を確認する #
data.info()で総行数/列型をチェックdata.isnull().sum()で欠損個数を確認data.duplicated().sum()で重複行を確認
(コードは省略、Notebook では print して確認)
5. 折れ線でざっと俯瞰する #
plt.figure(figsize=(12, 6))
plt.plot(data["Date"], data["Temp"])
plt.grid(axis="x")
plt.xlabel("Date")
plt.ylabel("Temp")
plt.title("Daily temperature")
plt.show()
連続して外れた点がないか、観測間隔が飛んでいないかを目視で確かめます。
6. トレンド線を重ねる #
3 次多項式でトレンドを推定するヘルパー関数を作成します。numpy.polyfit → poly1d で滑らかな曲線を描画できます。
def get_trend(timeseries, deg=3):
"""時系列のトレンド(多項式近似)を返す"""
x = list(range(len(timeseries)))
y = timeseries.values
coef = np.polyfit(x, y, deg)
trend = np.poly1d(coef)(x)
return pd.Series(data=trend, index=timeseries.index)
data["Trend"] = get_trend(data["Temp"])
plt.figure(figsize=(12, 6))
sns.lineplot(x=data["Date"], y=data["Temp"], alpha=0.5, label="Temp")
sns.lineplot(x=data["Date"], y=data["Trend"], label="Trend")
plt.grid(axis="x")
plt.legend()
plt.show()
メモ: 序盤でトレンドの有無を知っておくと、差分やスケーリングをどこで導入すべきか判断しやすくなります。
7. 分布と外れ値を把握する #
plt.figure(figsize=(12, 6))
plt.hist(x=data["Temp"], rwidth=0.8)
plt.xlabel("Temp")
plt.ylabel("頻度")
plt.grid(axis="y")
plt.show()
ヒストグラムで偏りや多峰性を確認し、必要に応じて Box-Cox やログ変換を検討します。
8. 自己相関で季節性を確認する #
pandas.plotting.autocorrelation_plot を使うとラグごとの自己相関が一目で分かります。365 付近に垂線を引いておくと年周期の有無が判断しやすくなります。
plt.figure(figsize=(12, 6))
pd.plotting.autocorrelation_plot(data["Temp"])
plt.grid()
plt.axvline(x=365)
plt.xlabel("Lag")
plt.ylabel("Autocorrelation")
plt.show()
9. 定常性テスト(ADF) #
Augmented Dickey-Fuller テストで単位根の有無を判定します。p 値が 0.05 未満なら定常とみなせます。
stattools.adfuller(data["Temp"], autolag="AIC")
出力例:
(-4.44, 0.00024, 20, 3629, {'1%': -3.43, '5%': -2.86, '10%': -2.57}, 16642.82)
- 統計量 -4.44 は 1%/5% 有意水準を下回っているので、帰無仮説(単位根あり)は棄却される。
- p 値 0.00024 も十分小さい。
10. トレンド抽出の注意点 #
データのスケールに敏感
長期的に指数的な増加がある場合、対数や年代ダミーなど事前変換を挟むと良い。多項式の次数を上げ過ぎない
高次項は外れ値に引っ張られやすいので、3~4 次程度で止める。備忘
長期トレンドを除去したバージョンをTemp_detrended、元データをTemp_rawなど名前を変えて持っておくと後で比較しやすい。
data_sub = data.copy()
data_sub["Temp"] = (
data_sub["Temp"] + np.log(data_sub["Date"].dt.year - 1980) * 10
)
data_sub["Trend"] = get_trend(data_sub["Temp"])
plt.figure(figsize=(12, 6))
sns.lineplot(x=data_sub["Date"], y=data_sub["Temp"], alpha=0.5, label="Temp")
sns.lineplot(x=data_sub["Date"], y=data_sub["Trend"], label="Trend")
plt.grid(axis="x")
plt.legend()
plt.show()
11. まとめ #
- データの健康診断: dtype, 欠損、重複、統計量を確認。
- 視覚化: 折れ線・ヒストグラム・自己相関で構造を直感的に把握。
- テスト: ADF で定常性を確認し、必要なら差分や変換を検討。
- トレンド関数: 1 度実装しておくと、他の前処理ノートでも再利用できる。