☀️

Python3 Pandas + Matplotlibを使用して、散布図と標準偏差を表示する

に公開

初めに

前回の記事で東京都の過去50年間の8月平均気温と移動平均の推移をグラフで描画したので、今回は散布図上に標準偏差(平均からどれくらいデータが散らばっているかを示す指標)を描画してみます。

過去100年間分の東京都の6月平均気温のデータを用いて標準偏差を算出します。
今年の6月が観測史上最高の平均気温だったとのことなので、実際にそれがどれくらい平均値からずれていたのかも確認してみましょう。

作成したコードはJupyter Notebook上で動作し、描画しています。

なお、開発環境の構築方法などについては、本記事では割愛します。

標準偏差について

環境・使用ライブラリ


コード

import pandas as pd
import matplotlib.pyplot as plt


# 1926年から2025年までの東京都の6月の平均気温のデータを定義
df = pd.DataFrame([
  {"年月": "1926年6月", "平均気温": 19.0},
  {"年月": "1927年6月", "平均気温": 20.5},
  {"年月": "1928年6月", "平均気温": 20.3},
  {"年月": "1929年6月", "平均気温": 20.6},
  {"年月": "1930年6月", "平均気温": 21.4},
  {"年月": "1931年6月", "平均気温": 20.4},
  {"年月": "1932年6月", "平均気温": 19.8},
  {"年月": "1933年6月", "平均気温": 21.9},
  {"年月": "1934年6月", "平均気温": 22.0},
  {"年月": "1935年6月", "平均気温": 21.5},
  {"年月": "1936年6月", "平均気温": 21.4},
  {"年月": "1937年6月", "平均気温": 19.6},
  {"年月": "1938年6月", "平均気温": 20.8},
  {"年月": "1939年6月", "平均気温": 20.7},
  {"年月": "1940年6月", "平均気温": 22.1},
  {"年月": "1941年6月", "平均気温": 20.8},
  {"年月": "1942年6月", "平均気温": 22.2},
  {"年月": "1943年6月", "平均気温": 21.5},
  {"年月": "1944年6月", "平均気温": 22.3},
  {"年月": "1945年6月", "平均気温": 20.4},
  {"年月": "1946年6月", "平均気温": 23.3},
  {"年月": "1947年6月", "平均気温": 19.2},
  {"年月": "1948年6月", "平均気温": 21.6},
  {"年月": "1949年6月", "平均気温": 19.4},
  {"年月": "1950年6月", "平均気温": 21.8},
  {"年月": "1951年6月", "平均気温": 21.2},
  {"年月": "1952年6月", "平均気温": 21.3},
  {"年月": "1953年6月", "平均気温": 20.6},
  {"年月": "1954年6月", "平均気温": 18.3},
  {"年月": "1955年6月", "平均気温": 22.7},
  {"年月": "1956年6月", "平均気温": 22.3},
  {"年月": "1957年6月", "平均気温": 19.8},
  {"年月": "1958年6月", "平均気温": 22.0},
  {"年月": "1959年6月", "平均気温": 20.4},
  {"年月": "1960年6月", "平均気温": 21.5},
  {"年月": "1961年6月", "平均気温": 22.6},
  {"年月": "1962年6月", "平均気温": 20.9},
  {"年月": "1963年6月", "平均気温": 21.8},
  {"年月": "1964年6月", "平均気温": 21.5},
  {"年月": "1965年6月", "平均気温": 21.6},
  {"年月": "1966年6月", "平均気温": 20.1},
  {"年月": "1967年6月", "平均気温": 23.0},
  {"年月": "1968年6月", "平均気温": 22.0},
  {"年月": "1969年6月", "平均気温": 21.8},
  {"年月": "1970年6月", "平均気温": 20.7},
  {"年月": "1971年6月", "平均気温": 21.3},
  {"年月": "1972年6月", "平均気温": 21.4},
  {"年月": "1973年6月", "平均気温": 19.8},
  {"年月": "1974年6月", "平均気温": 21.9},
  {"年月": "1975年6月", "平均気温": 21.6},
  {"年月": "1976年6月", "平均気温": 21.5},
  {"年月": "1977年6月", "平均気温": 20.9},
  {"年月": "1978年6月", "平均気温": 23.8},
  {"年月": "1979年6月", "平均気温": 24.4},
  {"年月": "1980年6月", "平均気温": 23.6},
  {"年月": "1981年6月", "平均気温": 20.2},
  {"年月": "1982年6月", "平均気温": 21.4},
  {"年月": "1983年6月", "平均気温": 20.5},
  {"年月": "1984年6月", "平均気温": 21.8},
  {"年月": "1985年6月", "平均気温": 20.2},
  {"年月": "1986年6月", "平均気温": 21.1},
  {"年月": "1987年6月", "平均気温": 22.1},
  {"年月": "1988年6月", "平均気温": 22.3},
  {"年月": "1989年6月", "平均気温": 20.7},
  {"年月": "1990年6月", "平均気温": 23.5},
  {"年月": "1991年6月", "平均気温": 23.6},
  {"年月": "1992年6月", "平均気温": 20.6},
  {"年月": "1993年6月", "平均気温": 21.7},
  {"年月": "1994年6月", "平均気温": 22.4},
  {"年月": "1995年6月", "平均気温": 20.4},
  {"年月": "1996年6月", "平均気温": 22.6},
  {"年月": "1997年6月", "平均気温": 22.7},
  {"年月": "1998年6月", "平均気温": 21.5},
  {"年月": "1999年6月", "平均気温": 22.8},
  {"年月": "2000年6月", "平均気温": 22.5},
  {"年月": "2001年6月", "平均気温": 23.1},
  {"年月": "2002年6月", "平均気温": 21.6},
  {"年月": "2003年6月", "平均気温": 23.2},
  {"年月": "2004年6月", "平均気温": 23.7},
  {"年月": "2005年6月", "平均気温": 23.2},
  {"年月": "2006年6月", "平均気温": 22.5},
  {"年月": "2007年6月", "平均気温": 23.2},
  {"年月": "2008年6月", "平均気温": 21.3},
  {"年月": "2009年6月", "平均気温": 22.5},
  {"年月": "2010年6月", "平均気温": 23.6},
  {"年月": "2011年6月", "平均気温": 22.8},
  {"年月": "2012年6月", "平均気温": 21.4},
  {"年月": "2013年6月", "平均気温": 22.9},
  {"年月": "2014年6月", "平均気温": 23.4},
  {"年月": "2015年6月", "平均気温": 22.1},
  {"年月": "2016年6月", "平均気温": 22.4},
  {"年月": "2017年6月", "平均気温": 22.0},
  {"年月": "2018年6月", "平均気温": 22.4},
  {"年月": "2019年6月", "平均気温": 21.8},
  {"年月": "2020年6月", "平均気温": 23.2},
  {"年月": "2021年6月", "平均気温": 22.7},
  {"年月": "2022年6月", "平均気温": 23.0},
  {"年月": "2023年6月", "平均気温": 23.2},
  {"年月": "2024年6月", "平均気温": 23.1},
  {"年月": "2025年6月", "平均気温": 24.7}
])
# 年をintに変換(X軸用)
df['年'] = df['年月'].str.extract(r'(\d+)').astype(int)

# 平均・標準偏差の計算(母集団として扱う場合は ddof=0、標本なら ddof=1)
mu = df['平均気温'].mean()
sigma = df['平均気温'].std(ddof=1)

# ±1σ, ±2σ, ±3σのラインを用意
y1 = mu - sigma
y2 = mu + sigma
y3 = mu - 2 * sigma
y4 = mu + 2 * sigma
y5 = mu - 3 * sigma
y6 = mu + 3 * sigma

plt.figure(figsize=(14, 6))
plt.scatter(df['年'], df['平均気温'], color='black', label='年毎の6月平均気温')
plt.axhline(mu, color='blue', linestyle='--', label=f'平均気温{mu:.2f}℃')
# ±3σ範囲(最も外側)
plt.fill_between(df['年'], y5, y3, color='red', alpha=0.1, label='±3σ')
plt.fill_between(df['年'], y4, y6, color='red', alpha=0.1)
# ±2σ範囲(内側2σ〜1σの部分)
plt.fill_between(df['年'], y3, y1, color='yellow', alpha=0.2, label='±2σ')
plt.fill_between(df['年'], y2, y4, color='yellow', alpha=0.2)
# ±1σ範囲(最も内側)
plt.fill_between(df['年'], y1, y2, color='green', alpha=0.3, label='±1σ')

plt.title('東京都(1926年〜2025年)の6月の平均気温と標準偏差')
plt.xlabel('年')
plt.ylabel('6月の平均気温(℃)')
plt.legend(loc='upper left')
plt.xticks(df['年'][::10])
plt.grid(True)
plt.tight_layout()
plt.show()

ポイント

標準偏差(シグマ)の計算

std()で標準偏差を算出しています。
変数y1y2y3y4y5y6で-3σから+3σの値を算出しています。

# 平均・標準偏差の計算(母集団として扱う場合は ddof=0、標本なら ddof=1)
mu = df['平均気温'].mean()
sigma = df['平均気温'].std(ddof=1)

# ±1σ, ±2σ, ±3σのラインを用意
y1 = mu - sigma
y2 = mu + sigma
y3 = mu - 2 * sigma
y4 = mu + 2 * sigma
y5 = mu - 3 * sigma
y6 = mu + 3 * sigma

年毎の6月平均気温と全体の平均気温及び、標準偏差(±1σ,±2σ,±3σ)のバンド幅の描画

plt.scatter(df['年'], df['平均気温'], color='black', label='年毎の6月平均気温')
plt.axhline(mu, color='blue', linestyle='--', label=f'平均気温{mu:.2f}℃')
# ±3σ範囲(最も外側)
plt.fill_between(df['年'], y5, y3, color='red', alpha=0.1, label='±3σ')
plt.fill_between(df['年'], y4, y6, color='red', alpha=0.1)
# ±2σ範囲(内側2σ〜1σの部分)
plt.fill_between(df['年'], y3, y1, color='yellow', alpha=0.2, label='±2σ')
plt.fill_between(df['年'], y2, y4, color='yellow', alpha=0.2)
# ±1σ範囲(最も内側)
plt.fill_between(df['年'], y1, y2, color='green', alpha=0.3, label='±1σ')

実行結果

Jupyter Notebook上で上記のコードを実行して描画されたグラフです。

緑色のバンド帯(-1σ〜+1σ)の間に収まる確率が約68.26%、黄色のバンド帯(-2σ〜+2σ)の間に収まる確率が約95.44%、赤色のバンド帯(-3σ〜+3σ)の間に収まる確率が約99.73%となっています。
今年の6月の平均気温(一番右上の点)は+2σ~+3σの間にあるため、確率論的には珍しい(±2σの範囲外なので4.56%)ことが分かります。


最後に

以上となります。

気温は地球温暖化などのトレンドで完全な正規分布ではありませんが、各年の平均気温がどのように分散していて、今年の6月の平均気温がどれくらい異常だったかを視覚的に確認できました。

分析に使用した東京都の平均気温のデータ

出典:気象庁ホームページ (https://www.data.jma.go.jp/risk/obsdl/index.php

レスキューナウテックブログ

Discussion