SOI の計算に入る前に、配列・平均・偏差・標準化・移動平均といった基本操作を、簡単なサンプルデータで練習する。
01 では Python 環境の構築を行い、02 ではすぐに SOI の計算に進む。しかし、SOI の計算では実は多くの操作をまとめて行っている。
そこで、まずは小さなサンプルデータで、これらの計算を1つずつ確認する。
| 書き方 | 意味 |
|---|---|
| np.array([...]) | 数値の並びを配列として作る |
| dtype=float | 小数として扱う指定 |
| np.mean(...) | 平均を求める |
| np.sum(...) | 合計を求める |
| x**2 | 2乗 |
| pd.Series(...) | 1列のデータとして扱う |
| rolling(window=3) | 3個ずつ窓をずらしながら計算する |
| np.corrcoef(x1, x2) | 2系列の相関係数を求める |
ここでは 12 か月分の簡単な配列を、仮の時系列データとして使う。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x = np.array([10, 11, 13, 12, 14, 15, 16, 15, 14, 13, 12, 11], dtype=float)
y = np.array([ 8, 9, 10, 11, 12, 14, 15, 14, 13, 12, 10, 9], dtype=float)
month = np.arange(1, 13)
print(x)
print(y)
まずは平均を計算する。
x_mean = np.mean(x)
y_mean = np.mean(y)
print("x mean =", x_mean)
print("y mean =", y_mean)
平均を引くと、各値が「平均からどれだけずれているか」がわかる。これを anomaly と考える。
x_anom = x - x_mean
y_anom = y - y_mean
print(x_anom)
print(y_anom)
print("mean of x_anom =", np.mean(x_anom))
データのばらつきを表す量が標準偏差である。標準偏差で割ると、スケールをそろえた「標準化データ」になる。
x_std = np.sqrt(np.sum(x_anom**2) / x_anom.size)
y_std = np.sqrt(np.sum(y_anom**2) / y_anom.size)
x_norm = x_anom / x_std
y_norm = y_anom / y_std
print("x std =", x_std)
print("y std =", y_std)
print(x_norm)
print(y_norm)
SOIでは、標準化した Tahiti と Darwin の差を用いる。ここでも同じことを試す。
diff = y_norm - x_norm
print(diff)
print("mean of diff =", np.mean(diff))
この差のばらつきを求めると、SOI計算に出てくる MSD と同じ考え方になる。
msd = np.sqrt(np.sum(diff**2) / diff.size)
print("MSD =", msd)
次に、時系列のノイズを少しなめらかにするため、移動平均を行う。
s = pd.Series(x)
x_ma3 = s.rolling(window=3, center=True).mean()
print(x_ma3)
図で確認する。
plt.figure(figsize=(8,4))
plt.plot(month, x, marker="o", label="original")
plt.plot(month, x_ma3, marker="o", label="3-point moving average")
plt.xlabel("Month")
plt.ylabel("Value")
plt.title("Moving Average")
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
自己相関とは、「同じ時系列を少しずらして比べたとき、どれくらい似ているか」を見る量である。
def autocorrelation_simple(a, lag):
x1 = a[:-lag]
x2 = a[lag:]
return np.corrcoef(x1, x2)[0,1]
for lag in [1, 2, 3]:
print(lag, autocorrelation_simple(x, lag))
ラグを増やしながら自己相関を描く。
lags = np.arange(1, 6)
acf = [autocorrelation_simple(x, lag) for lag in lags]
plt.figure(figsize=(7,4))
plt.bar(lags, acf)
plt.axhline(0, color="k")
plt.xlabel("Lag")
plt.ylabel("Autocorrelation")
plt.title("Autocorrelation (sample data)")
plt.tight_layout()
plt.show()
| このページの処理 | SOI計算で対応するもの |
|---|---|
| 平均 | climatology |
| 平均からの差 | anomaly |
| 標準偏差 | sDar, sTah |
| 標準化 | nDar, nTah |
| 2系列の差 | nTah - nDar |
| 差のばらつき | MSD |
| 移動平均 | SOI時系列のフィルタ処理 |
| 自己相関 | 周期性の観察 |
z = np.array([5, 6, 7, 8, 9], dtype=float)
print("z mean =", np.mean(z))
print("mean(x_norm) =", np.mean(x_norm))
print("std(x_norm) =", np.sqrt(np.sum((x_norm - np.mean(x_norm))**2) / x_norm.size))
x_ma5 = pd.Series(x).rolling(window=5, center=True).mean()
plt.figure(figsize=(8,4))
plt.plot(month, x, marker="o", label="original")
plt.plot(month, x_ma5, marker="o", label="5-point moving average")
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
lags = np.arange(1, 6)
acf = [autocorrelation_simple(x, lag) for lag in lags]
print(list(zip(lags, acf)))