Pythonで再現する:FAO食料価格と原油価格の相関分析(実装編)

特集・レポート

本記事では、FAO(国連食糧農業機関)の「食料価格指数」と、世界銀行(World Bank)の「エネルギー価格(Pink Sheet)」を活用し、Pythonでデータ取得から整形・可視化・相関分析までを一貫して再現します。

実際の統計データを扱いながら、穀物価格と原油価格の関係を分析し、相関係数0.877という高い連動性を確認。

食料とエネルギーがどのように“同じ波”で動くかを、コードとグラフで解き明かします。

本記事の内容はすべてPythonで再現可能です。

もし「統計分析やデータ可視化を基礎から学びたい」という方は、

👉 テックアカデミーのデータサイエンスコース

ようなオンライン講座で学んでおくと、この記事の再現がスムーズです。

概要

この記事では、FAO(国連食糧農業機関)の Food Price Index と、世界銀行(World Bank)の Commodity Price Data(Pink Sheet) を用い、Pythonでデータ取得・整形・可視化・相関分析を再現します。

メイン記事:食料価格とエネルギー価格の相関構造を探る(分析結果・経済的インサイトはこちら)


使用データ

データ名 提供機関 URL 更新頻度 備考
FAO Food Price Index FAO (United Nations) FAO公式サイト 月次 穀物・油脂・乳製品・砂糖・肉(2014–2016=100)
World Bank Commodity Prices (“Pink Sheet”) The World Bank World Bank公式サイト 月次 原油(Brent/WTI/Dubai)、天然ガスほか

これから紹介するコードは、すべてpandas・matplotlib・numpyなどの主要ライブラリで動作します。

Pythonの環境構築やライブラリの基本を学びたい場合は、

テックアカデミーのデータサイエンスコースでデータ分析を体系的に学ぶと

と、分析実装まで一気に理解できるのでおすすめです。

1. ライブラリの準備

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

2. 食料データの取得方法(ステップバイステップ)

ゴール

  • FAOのカテゴリ別・月次データ(穀物/油脂/乳製品/砂糖/肉)をCSVで入手

  • 2014–2016年=100 の名目指数を利用

  • 日付を YYYY-MM-01(各月1日)に統一し、エネルギーデータと結合可能に整形

手順

  1. FAO公式ページを開く
    FAO Food Price Index ページへ。

  2. ダウンロードセクション
    → ページ下部の “Download datasets” を確認。

  3. 月次CSVを選択
    → “CSV: Nominal indices from 1990 onwards (monthly)” をクリック。
    food_price_indices_data_*.csv(例:food_price_indices_data_oct25.csv)が保存されます。

  4. 内容を確認(代表列)

    • Date(YYYY-MM形式)

    • Food Price Index(総合)

    • Cereals / Oils / Dairy / Sugar / Meat
      ※版により Meat Price Index のような表記ゆれあり

  5. 基準と頻度

    • 基準:2014–2016=100(名目)

    • 頻度:月次(長期比較向き)

データ整形のポイント

  • FAOは YYYY-MM 表記 → YYYY-MM-01 に正規化しておくと結合が楽。

  • 最新月の確定タイミングが世界銀行とずれることがあるため、共通月のみの inner join が安全。

整形コード(FAO)

import pandas as pd

in_csv = "food_price_indices_data_oct25.csv" # ダウンロードしたCSV名
out_csv = "fao_food_price_monthly_clean.csv"

# 1) ヘッダなしで読んで、「Date」「Food Price Index」を含む行をヘッダに採用
raw = pd.read_csv(in_csv, header=None)

header_row = None
for i in range(min(10, len(raw))):
row_vals = [str(v) for v in raw.iloc[i].tolist()]
if "Date" in row_vals and "Food Price Index" in row_vals:
header_row = i
break
if header_row is None:
raise RuntimeError("ヘッダ行(Date, Food Price Index を含む行)が見つかりません。")

# 2) ヘッダ適用 & 本体切り出し
header = raw.iloc[header_row].tolist()
df = raw.iloc[header_row+1:].reset_index(drop=True).copy()
df.columns = header

# 3) Unnamed列を削除
df = df.loc[:, ~df.columns.astype(str).str.startswith("Unnamed")]

# 4) 列名の表記ゆれを統一
rename_map = {
"Month": "Date",
"Meat Price Index": "Meat",
"Dairy Price Index": "Dairy",
"Cereals Price Index": "Cereals",
"Oils Price Index": "Oils",
"Sugar Price Index": "Sugar",
}
df = df.rename(columns={c: rename_map.get(c, c) for c in df.columns})

# 5) 日付を YYYY-MM-01 に
df["Date"] = pd.to_datetime(df["Date"], errors="coerce")
df = df.dropna(subset=["Date"]).sort_values("Date")

# 6) 主要列のみ
keep = ["Date", "Food Price Index", "Cereals", "Oils", "Dairy", "Sugar", "Meat"]
df = df[[c for c in keep if c in df.columns]].reset_index(drop=True)

# 7) 保存
df.to_csv(out_csv, index=False, encoding="utf-8-sig")
print("✅ FAO整形完了:", out_csv)
print(df.tail())

3. FAO穀物価格の長期推移を可視化

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.family'] = 'MS Gothic'

plt.style.use('ggplot')
plt.rcParams['figure.figsize'] = [12, 9]

# 入力
fao_csv = "fao_food_price_monthly_clean.csv"
col_value = "Cereals"
last_n_months = 428 # 約35年

# 読み込み
df = pd.read_csv(fao_csv, parse_dates=["Date"])
df = df.sort_values("Date").dropna(subset=[col_value])

recent = df.tail(last_n_months)

# 可視化
plt.figure(figsize=(9, 4.5))
plt.plot(recent["Date"], recent[col_value], linewidth=2)
plt.title(f"FAO {col_value} Index (last {last_n_months} months)")
plt.xlabel("Date")
plt.ylabel("Index (2014–2016=100)")
plt.tight_layout()
plt.savefig("FAO Cereals Index.png")
plt.show()

4. エネルギーデータの取得方法(世界銀行 Pink Sheet)

ゴール

  • 世界銀行の Monthly Prices(Excel)から原油・天然ガスの月次データを入手

  • YYYY-MM-01 に整形し、FAOと結合できる形式に

手順(ダウンロード)

  1. World Bank Commodity Markets ページへ

  2. “Download historical data”(Commodity Price Data)

  3. “Monthly Prices – Excel” をクリック → CMO-Historical-Data-Monthly.xlsx を取得

ファイル構造(“Monthly Prices” シートの典型)

  • 上部:説明テキスト → 単位行($/bbl, $/MMBtu 等) → シリーズコード行CRUDE_BRENT 等)

  • 人間可読の列名Crude oil, Brent など)

  • 本体データ(1960M01 などの月次)

余分な行を飛ばし「人間可読の列名」をヘッダにするのがコツ。

Excelでの整形(簡易)

  • Power Queryで上部行を削除 → 最初の行を見出しに

  • M- に置換 → 日付型に(各月1日)

  • 必要列のみ選択(Brent/WTI/Europe Gas/Japan LNGなど)

  • 1982-01-01 より前の行は除外推奨

整形コード(World Bank, Python)

import pandas as pd
import re

# 設定
xlsx_path = "CMO-Historical-Data-Monthly.xlsx"
sheet_name = "Monthly Prices"
out_csv = "worldbank_energy_monthly_clean.csv"
cutoff_date = pd.Timestamp("1982-01-01")

wanted_regex = {
"Crude oil, Brent": re.compile(r"crude\s*oil.*brent", re.I),
"Crude oil, WTI": re.compile(r"crude\s*oil.*wti", re.I),
"Crude oil, Dubai": re.compile(r"crude\s*oil.*dubai", re.I),
"Natural gas, Europe": re.compile(r"natural\s*gas.*(europe|eu)", re.I),
"Natural gas, U.S.": re.compile(r"natural\s*gas.*(u\.?s\.?|united\s*states)", re.I),
"Liquefied natural gas, Japan": re.compile(r"(lng|liquefied\s*natural\s*gas).*(japan)", re.I),
}

# 1) ヘッダなしで読み込み
raw = pd.read_excel(xlsx_path, sheet_name=sheet_name, header=None)

# 2) データ開始行(YYYYMmm)
date_pat = re.compile(r"^\d{4}[mM]\d{2}$")
data_idx = None
for i in range(min(200, len(raw))):
v = str(raw.iat[i, 0]) if raw.shape[1] > 0 else ""
if date_pat.match(v):
data_idx = i
break
if data_idx is None:
raise RuntimeError("YYYYMmm 形式の最初のデータ行が見つかりません。")

# 3) 上方にヘッダ候補を探索(最大3行)
def score_header(row_vals):
s = " | ".join([str(x) for x in row_vals]).lower()
keys = ["crude", "oil", "natural gas", "brent", "wti", "dubai", "lng", "liquefied"]
return sum(k in s for k in keys)

header_candidates = []
for k in range(1, 4):
r = data_idx - k
if r >= 0:
row = raw.iloc[r].tolist()
header_candidates.append((r, score_header(row)))

header_row = max(header_candidates, key=lambda x: (x[1], x[0]))[0] if header_candidates else max(0, data_idx-1)
header = raw.iloc[header_row].tolist()

# 4) ヘッダ適用 & 切り出し
df = raw.iloc[data_idx:].reset_index(drop=True).copy()
df.columns = header
df.rename(columns={df.columns[0]: "Date"}, inplace=True)

# 5) 日付正規化(YYYYMmm → YYYY-MM-01)
df = df[df["Date"].astype(str).str.match(r"^\d{4}[mM]\d{2}$", na=False)].copy()
df["Date"] = pd.to_datetime(
df["Date"].astype(str).str.replace("M", "m").str.replace("m", "-", regex=False),
format="%Y-%m",
errors="coerce"
)

# 6) 欲しい列を正規表現で抽出
def find_col_by_regex(columns, pat):
for c in columns:
if pat.search(str(c)):
return c
return None

found_map = {"Date": "Date"}
for label, pat in wanted_regex.items():
hit = find_col_by_regex(df.columns, pat)
if hit:
found_map[label] = hit

df_out = df[list(found_map.values())].copy()
df_out.columns = list(found_map.keys())

# 7) 1982年以前を除外 → 並べ替え
df_out = df_out[df_out["Date"] >= cutoff_date].sort_values("Date").reset_index(drop=True)

# 8) 保存
df_out.to_csv(out_csv, index=False, encoding="utf-8-sig")

print("✅ 整形完了:", out_csv)
print("抽出列:", df_out.columns.tolist())
print(df_out.head(3))
print(df_out.tail(3))

5. エネルギー価格の長期推移を可視化(Brent)

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.family'] = 'MS Gothic'

plt.style.use('ggplot')
plt.rcParams['figure.figsize'] = [12, 9]

energy_csv = "worldbank_energy_monthly_clean.csv"
col_value = "Crude oil, Brent"
last_n_months = 428

df = pd.read_csv(energy_csv, parse_dates=["Date"])
df = df.sort_values("Date").dropna(subset=[col_value])
recent = df.tail(last_n_months)

plt.figure(figsize=(9, 4.5))
plt.plot(recent["Date"], recent[col_value], linewidth=2)
plt.title(f"{col_value} Price (last {last_n_months} months)")
plt.xlabel("Date")
plt.ylabel("Price (US$/barrel)")
plt.tight_layout()
plt.savefig("Brent Crude Oil Price.png")
plt.show()

6. ここから実装:統合と相関分析

入力ファイル

  • fao_food_price_monthly_clean.csvDate, Food Price Index, Cereals, Oils, Dairy, Sugar, Meat

  • worldbank_energy_monthly_clean.csvDate, Crude oil, Brent ほか)

自動でやること

  1. Dateinner join(共通月のみ)

  2. 2系列の重ね合わせ(Cereals vs Brent)

  3. 散布図+回帰直線 & 相関係数(Pearson)

列の差し替えで他カテゴリ(Oils など)・他エネルギー系列(Natural gas, Europe など)にも即対応。

統合・相関分析コード(matplotlibのみ)

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 1) 読み込み
fao = pd.read_csv("fao_food_price_monthly_clean.csv", parse_dates=["Date"])
energy = pd.read_csv("worldbank_energy_monthly_clean.csv", parse_dates=["Date"])

# 2) 必要列
fao = fao[["Date", "Cereals", "Food Price Index"]]
energy = energy[["Date", "Crude oil, Brent"]]

# 3) 結合
merged = pd.merge(fao, energy, on="Date", how="inner").sort_values("Date")
merged = merged.dropna(subset=["Cereals", "Crude oil, Brent"])

# 4) 相関係数
corr = merged["Cereals"].corr(merged["Crude oil, Brent"])
print(f"相関係数(Cereals vs Brent): {corr:.3f}")

# 5) 重ね合わせ(2軸)
fig, ax1 = plt.subplots(figsize=(10, 5))
ax1.set_title("FAO Cereals Index vs Brent Crude Oil Price", fontsize=13)
ax1.plot(merged["Date"], merged["Cereals"], label="Cereals Index", linewidth=2)
ax1.set_ylabel("Cereals Index (2014–2016=100)")

ax2 = ax1.twinx()
ax2.plot(merged["Date"], merged["Crude oil, Brent"], label="Brent Crude", linewidth=2)
ax2.set_ylabel("Brent Oil Price (US$/barrel)")

fig.tight_layout()
plt.savefig("Cereals vs Brent.png")
plt.show()

# 6) 散布図+回帰直線(numpyで単回帰)
x = merged["Crude oil, Brent"].values
y = merged["Cereals"].values
m, b = np.polyfit(x, y, 1)

plt.figure(figsize=(6, 6))
plt.scatter(x, y, alpha=0.5)
plt.plot(x, m*x + b, color="red", linewidth=2)
plt.title("Cereals vs Brent Crude Oil — Correlation Analysis")
plt.xlabel("Brent Crude Oil Price (US$/barrel)")
plt.ylabel("Cereals Index (2014–2016=100)")
plt.tight_layout()
plt.savefig("Cereals vs Brent Corr.png")
plt.show()

7. よくあるつまずき(FAQ)

Date が見つからない/型が合わない
→ 整形段階で YYYY-MM-01 に統一。parse_dates=[“Date”] を忘れずに。

列名が違う(例:Meat Price Index)
→ FAO整形コードの rename_map を活用。

最新月が片方だけにある
→ inner join で共通月のみ分析。

長期比較で単位差が気になる
→ 変化率や基準化(初期月=100)で形の比較に切替。

以上で実装手順は完了です。

相関係数やグラフから読み取れる「世界経済の構造的な連動」については、

👉 分析編の記事で詳しく解説しています。

8. まとめ

本記事は、FAOの食料価格指数世界銀行のエネルギー価格統計をもとに、
Python(pandas・matplotlib・numpy)を使ってデータ処理から相関分析までを再現した実装ガイドです。

公開データだけで以下の分析が可能であることを確認しました。

  • FAOとWorld Bankの月次データを整形・統合

  • 穀物と原油の時系列を重ね合わせ、価格の共動性を可視化

  • ピアソン相関係数(0.877)により、両市場の強い正の関係を定量化

この結果は、**「エネルギー価格が食料価格を先導する構造」**を裏付けるものであり、
統計や経済分析の現場で応用できる再現性の高い分析手順を示しています。

もし今後さらに発展させたい場合は、以下のような分析もおすすめです:

  • ラグ相関分析:原油高から穀物高までの時間差を定量化

  • 回帰モデル構築:原油価格を説明変数とする予測式の作成

  • 可視化強化:Plotlyなどでインタラクティブに比較

このコードは「実務でも使える再現性重視の分析テンプレート」です。

データ分析を学びたい方や、世界インフレ構造をPythonで理解したい方の実践ガイドとして活用してください。

本記事で扱った分析は、すべてPythonで再現できます。

自分の手を動かして分析をしてみたい方は、

👉テックアカデミーのデータサイエンスコースがおすすめです。

コメント

タイトルとURLをコピーしました