01.5 Python計算トレーニング

SOI の計算に入る前に、配列・平均・偏差・標準化・移動平均といった基本操作を、簡単なサンプルデータで練習する。

位置づけ
01 Python環境の構築 と 02 SOI計算 の間
到達目標
SOI 計算で使う処理を、小さな例で理解する
方針
いきなり実データに入らず、まずは練習用データで確認する

1. なぜこの練習が必要か

01 では Python 環境の構築を行い、02 ではすぐに SOI の計算に進む。しかし、SOI の計算では実は多くの操作をまとめて行っている。

そこで、まずは小さなサンプルデータで、これらの計算を1つずつ確認する。

このページをやっておくと、02 の SOI 計算のコードがかなり読みやすくなる。

Pythonでよく出る書き方

書き方意味
np.array([...])数値の並びを配列として作る
dtype=float小数として扱う指定
np.mean(...)平均を求める
np.sum(...)合計を求める
x**22乗
pd.Series(...)1列のデータとして扱う
rolling(window=3)3個ずつ窓をずらしながら計算する
np.corrcoef(x1, x2)2系列の相関係数を求める
Python は「関数名」と「かっこの中の指示」を分けて読むと理解しやすい。たとえば rolling(window=3, center=True) なら、rolling が機能名、window や center が設定である。

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)

このブロックで新しく出るもの

  • np.array:配列を作る
  • dtype=float:整数ではなく小数で扱う
  • np.arange(1, 13):1から12までの連番を作る
xy は、ここでは「2つの観測地点の月ごとの値」だと思えばよい。SOIではこれが Darwin と Tahiti に対応する。
STEP 1

3. 配列と平均

まずは平均を計算する。

x_mean = np.mean(x)
y_mean = np.mean(y)

print("x mean =", x_mean)
print("y mean =", y_mean)

このブロックで新しく出るもの

  • np.mean(x):x の平均
  • print(...):結果を画面に出す

確認

演習
自分で z = np.array([...]) を作り、平均を計算せよ。
STEP 2

4. 偏差(anomaly)

平均を引くと、各値が「平均からどれだけずれているか」がわかる。これを 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 - x_mean:配列の各要素から平均を引く
  • np.mean(x_anom):偏差の平均を確認する

確認

SOI計算では climatology を引いて anomaly を作る。ここでは単純に全期間平均を引いている。
STEP 3

5. 標準偏差と標準化

データのばらつきを表す量が標準偏差である。標準偏差で割ると、スケールをそろえた「標準化データ」になる。

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)

このブロックで新しく出るもの

  • np.sqrt(...):平方根
  • x_anom.size:配列の要素数
  • x_anom / x_std:各要素を標準偏差で割る

確認

演習
x_anom / x_std を実行したあと、平均が 0 に近いか、標準偏差が 1 に近いか確認せよ。
STEP 4

6. 2系列の差

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)

確認

STEP 5

7. 移動平均

次に、時系列のノイズを少しなめらかにするため、移動平均を行う。

s = pd.Series(x)
x_ma3 = s.rolling(window=3, center=True).mean()

print(x_ma3)

このブロックで新しく出るもの

  • pd.Series(x):x を 1 列データとして扱う
  • rolling(window=3, center=True):3点移動平均を中央配置で計算する
  • mean():各窓の平均を計算する

図で確認する。

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()

確認

演習
window=5 にするとどう変わるか確かめよ。
STEP 6

8. 自己相関の考え方

自己相関とは、「同じ時系列を少しずらして比べたとき、どれくらい似ているか」を見る量である。

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の自己相関では、より長い時系列に対してラグを -120〜120 か月ずつ取っていた。ここではまず小さい例で考え方だけ確認する。

9. SOI計算との対応

このページの処理SOI計算で対応するもの
平均climatology
平均からの差anomaly
標準偏差sDar, sTah
標準化nDar, nTah
2系列の差nTah - nDar
差のばらつきMSD
移動平均SOI時系列のフィルタ処理
自己相関周期性の観察
このページで計算の意味を押さえておけば、02 の SOI 計算コードは「新しい処理の寄せ集め」ではなく、「すでに練習した処理の組み合わせ」として読める。

付録:演習の解答例

STEP1 演習

z = np.array([5, 6, 7, 8, 9], dtype=float)
print("z mean =", np.mean(z))

STEP3 演習(標準化の確認)

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))

STEP5 演習(window変更)

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()

STEP6 自己相関

lags = np.arange(1, 6)
acf = [autocorrelation_simple(x, lag) for lag in lags]
print(list(zip(lags, acf)))
ここでは「どう書くか」よりも、「何をしているか」を理解することが重要である。