売上や利益の成長率は、企業の 稼ぐ力の伸び を見るための基本指標です。本記事では YoY(前年比)・QoQ(前期比)・CAGR(年平均成長率)の計算式と、pandas での集計・可視化手順を整理します。

目次

  1. 成長率の代表的な指標
  2. YoY の計算式
  3. QoQ の計算式
  4. CAGR の計算式
  5. サンプル DataFrame を用意する
  6. YoY を計算する
  7. QoQ を計算する
  8. CAGR を計算する
  9. 折れ線で時系列を可視化する
  10. 売上と利益で成長率を見比べる
  11. 成長率を読むときの注意

成長率の代表的な指標

成長率には複数の表現があり、用途によって使い分けます。

指標比較対象主な使いどころ
YoY1 年前の同期季節性のある業界(小売・観光など)
QoQ直前の四半期直近のトレンド変化を見る
CAGR期初と期末を結ぶ年率長期の平均成長スピード

YoY は四半期データを 前年同四半期 と比較するのが標準で、季節要因を取り除けます。

YoY の計算式

YoY(Year-over-Year)は次の式で計算します。

YoY=当期前年同期前年同期×100(%)\text{YoY} = \frac{\text{当期} - \text{前年同期}}{\text{前年同期}} \times 100\,(\%)

たとえば 2024Q4 の売上が 1,200 億円、2023Q4 が 1,000 億円なら、YoY = (1200 - 1000) / 1000 × 100 = 20%。

QoQ の計算式

QoQ(Quarter-over-Quarter)は次の式です。

QoQ=当四半期前四半期前四半期×100(%)\text{QoQ} = \frac{\text{当四半期} - \text{前四半期}}{\text{前四半期}} \times 100\,(\%)

季節要因のある事業では、QoQ は単純比較しにくくなります。たとえば小売業の年末四半期と直後の Q1 を単純に QoQ で比較すると、季節要因の影響が大きく出ます。

CAGR の計算式

CAGR(Compound Annual Growth Rate)は、複利を考慮した 平均年率成長 です。

CAGR=(期末値期初値)1/n1\text{CAGR} = \left( \frac{\text{期末値}}{\text{期初値}} \right)^{1/n} - 1

nn は年数です。たとえば 5 年で売上が 100 億円から 200 億円になった場合、

CAGR=(200/100)1/510.149=14.9%\text{CAGR} = (200 / 100)^{1/5} - 1 \approx 0.149 = 14.9\%

長期の成長スピードを 1 つの数字で表すのに便利ですが、間の年のばらつき は見えません。CAGR と一緒に時系列の折れ線を見るのが安全です。

サンプル DataFrame を用意する

説明用の四半期データを用意します。

import numpy as np
import pandas as pd
dates = pd.date_range("2021-03-31", periods=16, freq="QE") # 4 年分の四半期末
np.random.seed(0)
trend_a = 1000 + np.linspace(0, 600, 16)
trend_b = 800 + np.linspace(0, 200, 16)
seasonal = np.tile([0, -50, -30, 80], 4) # 季節要因
noise_a = np.random.normal(0, 30, 16)
noise_b = np.random.normal(0, 20, 16)
df = pd.DataFrame({
"Code": ["1301"] * 16 + ["1302"] * 16,
"fiscal_q": list(dates) * 2,
"Sales": list((trend_a + seasonal + noise_a).round(1)) +
list((trend_b + seasonal + noise_b).round(1)),
})
print(df.head())

fiscal_q を四半期末日とし、銘柄 1301 / 1302 の売上を持たせています。実データでは J-Quants の財務データから取得します(#6-6「財務情報を取得する (/fins/summary)」)。

YoY を計算する

YoY は 同じ銘柄・前年同期 を取り出して計算します。

df = df.sort_values(["Code", "fiscal_q"]).reset_index(drop=True)
df["sales_yoy"] = (
df.groupby("Code")["Sales"]
.pct_change(periods=4) * 100
)
print(df.tail(8).round(2))

pct_change(periods=4) で「4 期前(= 1 年前の同四半期)」との変化率を出します。groupby("Code") を入れないと、銘柄をまたいで計算してしまうため必ず指定します。

QoQ を計算する

QoQ は直前期と比較するので periods=1 です。

df["sales_qoq"] = (
df.groupby("Code")["Sales"]
.pct_change(periods=1) * 100
).round(2)

季節性が強い場合、QoQ の数字をそのまま「成長」と読まないようにします。

CAGR を計算する

CAGR は期初と期末を取り出して計算します。

def cagr(start: float, end: float, years: float) -> float | None:
if start is None or start <= 0 or years <= 0:
return None
return (end / start) ** (1.0 / years) - 1.0
# 銘柄ごとの期初・期末売上から 4 年 CAGR を出す
agg = df.groupby("Code")["Sales"].agg(["first", "last"])
agg["cagr_pct"] = agg.apply(
lambda r: cagr(r["first"], r["last"], years=3.75) * 100, axis=1
).round(2)
print(agg)

years は四半期間隔から換算します。16 四半期 = 4 年分のデータですが、期初を最初、期末を最後に取ると間隔は 15 四半期 = 3.75 年です(両端を含む数え方の違いに注意)。

折れ線で時系列を可視化する

成長率は時系列で見ると、トレンドの変化が分かりやすくなります。

import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(8, 4))
for tk, sub in df.groupby("Code"):
ax.plot(sub["fiscal_q"], sub["sales_yoy"], marker="o", label=tk)
ax.axhline(0, color="gray", linewidth=0.8)
ax.set_title("売上 YoY(%)")
ax.set_xlabel("四半期")
ax.set_ylabel("YoY (%)")
ax.legend(title="ticker")
fig.autofmt_xdate()
plt.tight_layout()
# fig.savefig("yoy.png", dpi=150)

YoY の折れ線は 0% を境に正負を読む ことが多いため、ゼロ線を補助線として引いておくと見やすくなります。

2 銘柄の売上 YoY 推移を比較した折れ線グラフ

売上と利益で成長率を見比べる

売上だけでなく、利益(営業利益・純利益)についても成長率を出すと、「売上は伸びているが利益が伸びない」「両方伸びている」「利益のほうが伸びている」といったパターンが見えます。

# サンプル: 売上に 8% の利益率が乗っているとする
df["op_income"] = (df["Sales"] * 0.08).round(1)
df["op_yoy"] = (
df.groupby("Code")["op_income"].pct_change(periods=4) * 100
).round(2)
print(df.groupby("Code")[["sales_yoy", "op_yoy"]].tail(4))

利益の YoY が売上 YoY より大きい場合、利益率が改善 していることを示唆します。

成長率を読むときの注意

成長率はそのまま受け取らず、次の点に気をつけます。

  • 基準値が小さい時 の成長率は値が大きく出やすい(分母が小さいだけ)
  • 一過性の 特別損益・買収効果 で利益 YoY が大きくぶれる
  • 会計基準変更 や決算期変更で連続性が崩れる年がある
  • 5 年 CAGR と直近 1 年 YoY が乖離している場合、トレンドが変化している可能性

長期の CAGR と直近の YoY / QoQ をセットで見ると、成長の「平均値」と「直近の温度感」を両方押さえられます。

生成AI へのプロンプト例

四半期売上と営業利益の YoY を 1 つのチャートで見せたい場合の例です。

入力 DataFrame に次の列があります(売上は J-Quants API に準拠)。
- Code (str): 1 銘柄想定
- fiscal_q (datetime64[ns]): 四半期末
- Sales (float)
- op_income (float)
依頼:
- Sales と op_income の YoY(前年同期比、%)を計算
- 同じ図に 2 本の折れ線として描画(色を分け、凡例を付ける)
- 0% の水平線を補助として描く
- タイトル・軸ラベル・凡例は日本語
要件: pandas 2.2 系 + matplotlib。関数化し、docstring は日本語。

まとめ

  • 成長率は YoY / QoQ / CAGR を使い分ける
  • pandas では groupby(銘柄).pct_change(periods=N) で計算する
  • 季節性のある業種では QoQ を単純比較しない
  • 売上と利益の成長率を見比べると利益率の変化が見える