GDPと構成要素#

in English or the language of your choice.

import japanize_matplotlib
import numpy as np
import pandas as pd
import py4macro

# 警告メッセージを非表示
import warnings
warnings.filterwarnings("ignore")

はじめに#

人の心の中を知ることはできない。友人,同僚,パートナー,親族もそうである。また何十年も連れ添った夫婦でさえも完全にお互いの心の中を分かっているとは言い難いだろう。しかし話し言葉やその内容,行動から心の中を推測することは可能である。実際,我々は日常そうしており,人間関係を豊かにする為には必須でる。経済も同じである。経済の動きの裏にある「真のメカニズム」は完全に把握されていない。アダム・スミスの時代に比べると,「熟練夫婦」に匹敵するほど知見は蓄積されたかも知れないが,今でも「真のメカニズム」が100%解明されたとは言い難い。経済学者にとってできることは,経済の「言動」であるデータを観察し「真のメカニズム」について想像を巡らすことである。人の言動に注意を払わずに人の心の中を想像するのは「妄想」となり,データを無視して経済を考えるのは「空想」となってしまう危険性がある。

人の心の中 \(\Longleftrightarrow\) 経済の真のメカニズム

人の言動 \(\Longleftrightarrow\) 経済データ

この章はマクロ・データの特徴を理解することを目的とする。統計量やプロットを駆使して異なるマクロ・データの特性を炙り出し,経済の「言動」に注目しようということである。特に,以下では国内総生産(GDP)とその構成要素に着目し議論を進める。

使うデータはpy4macroに含まれる日本の四半期データである。1980年から1993年のデータと1994年から2021年までの2つのデータ・セットを組み合わせて作成した。データを読み込むには次のようにする。

py4macro.data('jpn-q')

ここでjpnはJapan,qはquerterlyを表している。変数の定義を表示するにはdescription=Trueの引数を追加する。

py4macro.data('jpn-q', description=True)
    | `gdp`: 国内総生産(GDP)
    | `consumption`: 消費
    | `investment`: 投資
    | `government`: 政府支出
    | `exports`: 輸出
    | `imports`: 輸入
    | `capital`: 資本ストック
    | `employed`: 就業者数
    | `unemployed`: 失業者数
    | `unemployment_rate`: 失業率
    | `hours`: 労働者一人当たり月平均労働時間
    | `total_hours`: 月平均総労働時間(`employed`X`hours`)
    | `inflation`: インフレ率
    | `price`: 消費者物価指数
    | `deflator`: GDPデフレーター
    |
    | * 四半期データ
    |
    | <出典>
    | GDPとその構成要素
    |    * 1994年Q1~2021年Q4
    |        * 実額・四半期・実質季節調整系列(年換算)
    |        * 2015暦年(平成27年)連鎖価格
    |        * 単位:10億円
    |        * 国民経済計算(GDP統計)
    |    * 1980年Q1~1993年Q4
    |        * 実額・四半期・実質季節調整系列(年換算)
    |        * 平成27年基準支出側GDP系列簡易遡及(参考系列であり上のデータと接続可能)
    |        * 単位:10億円
    |        * 国民経済計算(GDP統計)
    |
    | 実質資本ストック
    |   * 1994年Q1~2019年Q4
    |        * 平成25年基準
    |        * 単位:10億円
    |        * 国民経済計算(GDP統計)
    |   * 1980年Q1~1993年Q4
    |        * 平成25年基準遡及系列
    |        * 単位:10億円
    |        * 国民経済計算(GDP統計)
    |
    | 就業者数,失業者数,失業率
    |   * 総務省「労働力調査」
    |   * 単位:万人,%
    |
    | 労働者一人当たり月平均労働時間
    |   * 厚生労働省「毎月勤労統計調査」
    |   * 30 人以上(一般・パート)、月間実労働時間(総実労働時間)
    |   * 2020年の平均を100に基準化
    |
    | インフレ率
    |   * 景気動向指数(速報,改訂値,月次,原数値の前年同月比)から四半期平均として計算
    |
    | 消費者物価指数
    |   * 2020年基準
    |   * 「中分類指数(全国)<時系列表>【月次】」の四半期平均として計算
    |   * 簡便的に移動平均を使い季節調整を施している
    |
    | GDPデフレーター
    |   * 1994年Q1~2019年Q4
    |       * 2015年(平成27年)基準
    |       * 季節調整系列
    |   * 1980年Q1~1993年Q4
    |       * 2015年(平成27年)基準遡及系列
    |       * 季節調整系列

このデータ・セットにはGDPとその構成要素以外も含まれているが,それらは次章で使うことになる。

まずデータを読み込んで最初の5行を表示してみよう。

df = py4macro.data('jpn-q')
df.head()
gdp consumption investment government exports imports capital employed unemployed unemployment_rate hours total_hours inflation price deflator
1980-03-31 269747.5 153290.7 65029.2 73039.5 18383.8 24278.8 834219.7 5506.000000 107.666667 1.900000 124.7 686598.200000 5.766667 71.015699 91.2
1980-06-30 268521.8 153551.9 65316.6 72164.5 18631.4 25454.5 843000.2 5525.666667 110.000000 1.966667 124.8 689603.200000 8.166667 72.907806 93.4
1980-09-30 274183.1 155580.0 65765.9 72663.8 18449.3 23885.7 854753.4 5561.333333 116.000000 2.033333 124.0 689605.333333 8.200000 73.898630 94.4
1980-12-31 279601.8 156162.4 66017.5 74761.1 19705.4 23716.5 868241.2 5551.333333 123.333333 2.166667 123.9 687810.200000 8.100000 74.771830 95.4
1981-03-31 281995.7 156757.7 66259.0 76127.6 20289.5 24174.1 879629.9 5568.666667 124.333333 2.200000 123.7 688844.066667 6.833333 75.694271 95.6

列には変数が並んでいるのが確認できる。行はインデックスではなくラベルとなっており,年・四半期を示している。例えば,1980-3-31は1980年第1四半期であり,その最終日がラベルとして使われている。.info()を使って確認してみる。

df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 168 entries, 1980-03-31 to 2021-12-31
Data columns (total 15 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   gdp                168 non-null    float64
 1   consumption        168 non-null    float64
 2   investment         168 non-null    float64
 3   government         168 non-null    float64
 4   exports            168 non-null    float64
 5   imports            168 non-null    float64
 6   capital            168 non-null    float64
 7   employed           168 non-null    float64
 8   unemployed         168 non-null    float64
 9   unemployment_rate  168 non-null    float64
 10  hours              168 non-null    float64
 11  total_hours        168 non-null    float64
 12  inflation          168 non-null    float64
 13  price              168 non-null    float64
 14  deflator           168 non-null    float64
dtypes: float64(15)
memory usage: 21.0 KB

表示の上から2行目にDatetimeIndexとあるが,行ラベルのことを表しており,時系列データ用となっている。具体的な説明は割愛するが,時系列データが扱いやすくなりプロットする際にも便利である。

GDPとその変化#

まずGDPを図示しよう。

df['gdp'].plot(title='GDP')
pass
_images/ed7d1d24f6835f710bfc8ad7c8e79c07c75757bc049eac52ee0c15663fb997e0.png

長期的には上昇トレンドであることが分かる。これが経済成長である。一方で,よく観察するとギザギザに動いていることも確認できる。景気変動である。小さい上下の動きもあれば,より大きな動きもある。例えば,2008年のリーマン・ショック,そして2020年のコロナ禍の影響でGDPは大きく下落している。

(問4)なぜ景気変動は起こるのか?

これがマクロ経済学のもう一つのBig Questionである。この章以降は問4を中心にマクロ経済を考察することになる。

上の図には2022年第1四半期以降のデータは含まれていない。参考に最新のデータを含む図を下にに表示する。

Hide code cell source
from IPython.display import IFrame
IFrame(src='https://fred.stlouisfed.org/graph/graph-landing.php?g=BOLN&width=420&height=320',
       width=450, height=330)

この図は米国セントルイス連邦準備銀行が管理するFederal Reserve Economic Data (FRED)と呼ばれるデータ・ベースからライブでダウンロードして表示している。

py4macroを使った上の図もしくはFREDの図にあるGDPは水準を表しているため,GDPの成長率を直接読み取り異なる時期の成長率を比べることは難しい。しかし,それを可能にするのが対数化したGDPのプロットである。まず,なぜそうなのかを簡単に説明しよう。

変数xの成長率\(g_x\)は次の式で定義される。

\[ 1+g_x=\frac{x_{t+1}}{x_{t}} \]

ここで\(g_x\)の値は,例えば0.022%)のような値となる。この式の両辺に対数を取り,近似を使うと次のように書き直すことができる。

\[ \log(1+g_x)=\log(x_{t+1})-\log(x_{t}) \]
\[ \qquad\qquad\quad\Downarrow\text{左辺を近似}\;\log(1+g_x)\approx g_x \]
(99)#\[ g_x\approx\log(x_{t+1})-\log(x_{t}) \]

xの成長率である\(g_x\)は,xの対数の差分ということになる。即ち,縦軸にxの対数,横軸に時間をおけば,プロットの傾きはxの成長率と等しいことになる。

では実際にプロットしよう。

df['gdp_log'] = np.log(df['gdp'])

df['gdp_log'].plot(title='GDP(対数)')
pass
_images/84dffe99dab1d7ec60df31360ba0097c08232b58778270ec28f74ea07148b0e2.png

プロットの傾きは四半期ごとのGDPの成長率であり,成長率が変化しているのがわかる。また,2008年のリーマン・ショックとコロナ禍により成長率が大きく下落していることが確認できる。景気循環により成長率が小刻みに,また時には大きく変化している。

次に,長期的な視点で図を眺めてみよう。1980年から1990年までの間に直線のトレンドを描くことができる。その傾きが平均成長率である。同様に,1990年から2020年までの直線トレンドを描くこともできるが,傾きが緩やかになっていることに気づくのではないだろうか。1991年頃のバブル崩壊の影響により,その後のGDPの伸びが鈍化していることがわかる。「失われた10年」,「失われた20年」と言われていたが,今では「失われた30年」と言われる所以である。

次に(99)を使い四半期成長率を計算してみよう。

df['gdp_growth_quarter'] = 100*df['gdp_log'].diff()   # 1

# 2
ax_ = df['gdp_growth_quarter'].plot(title='GDP四半期成長率(%)')
ax_.grid()   # 3
pass
_images/7d18efe967a056280f9db888b79f91b50a517665986e4d28ee6c0cf251890d4f.png

新聞などで「前年同期比成長率」という表現をみたことがあると思うが,diff()の引数を4にすることにより,前年同期比の成長率を計算することができる。それを図示してみよう。

df['gdp_growth_annual'] =  100*df['gdp_log'].diff(4)

ax_ = df['gdp_growth_annual'].plot(title='GDP前年同期比成長率(%)')
ax_.grid()
pass
_images/1030a1b96e6eba30c0aaa538cba2d0f5ff3b9ae802a607833ac9afde43cf11cd.png

上の図と比べると縦軸の幅の違いに気づくだろう。最高値と最小値を計算してみよう。

df['gdp_growth_annual'].max(), df['gdp_growth_annual'].min()
(7.591566394121507, -10.61353111987522)

1980年代後半ののバブル景気には約7.6%増加しているが,コロナ禍では約10%以上下落している。

次の点を知っておくのも有用だろう。

  • 次の式を使うと四半期成長率を年率換算することもできる。

    \[ g_{\text{年率換算成長率}}=\left(1+g_{\text{四半期成長率}}\right)^4-1 \]

    \(g_{\text{四半期成長率}}\)が4期続くことを想定した成長率である。

  • 年次データを使うとGDPの値は均されるので変化率は低めに出る。

GDPの構成要素#

次式は所得恒等式である。

    GDP=消費+投資+政府支出+純貿易(輸出ー輸入)

GDPに対してそれぞれ構成要素は何%を占め,どのように推移したかを図示する為に,まず変数を計算する。

# 消費の割合
con_gdp_ratio = 100 * df['consumption'] / df['gdp']

# 投資の割合
inv_gdp_ratio = 100 * df['investment'] / df['gdp']

# 政府支出の割合
gov_gdp_ratio = 100 * df['government'] / df['gdp']

# 純輸出の割合
net_exp_gdp_ratio = 100 * ( df['exports']-df['imports'] ) / df['gdp']

それぞれの平均をforループで計算し表示してみよう。

ratio_list = [con_gdp_ratio,inv_gdp_ratio,
              gov_gdp_ratio,net_exp_gdp_ratio]

label_list = ['Consumption','Investment','Gov Exp','Net Exports']

for r, l in zip(ratio_list, label_list):
    
    avr = r.mean()
    
    print(l, f'\t{avr:.1f}')
Consumption 	55.6
Investment 	21.8
Gov Exp 	25.3
Net Exports 	-1.1

消費はGDPの60%近くあり,GDPの約1/4が政府支出となっている。消費とは対照的に,投資は約20%であり消費の約3分の1である。(小数点第一位までしか表示していないため合計は100にならない。)

次に推移を確認する。同じようにforループを使うと簡単に表示できる。

for r, l in zip(ratio_list,label_list):
    
    r.plot(label=l, legend=True)
_images/ab5f59a504de57e42cb95ae12255fed2629a4d6661f6ac628bb15db6c4baeecc.png

景気の動向によって上下することがわかる。例えば,リマン・ショック後には投資が大きく下落し少しずつしか上昇しない。一方,景気悪化に反応し政府支出の割合は上昇している。またバブル景気(1986年から1991年まで)ではその逆が起こっており,順位が逆転する程である。コロナ禍の影響もプロットにハッキリと現れている。

トレンドと変動#

説明#

上の分析から明らかなことは,マクロ変数は変動するということであり,正しくそれが景気循環を表している。ここでは景気循環について,もう一歩踏み込んで考えてみる。

マクロ変数はトレンドと変動(サイクル)に分解することができる。例えば,\(Y\)をGDPとすると次式のように2つの項で表すことができる。

(100)#\[ Y=Y_t^{\text{trend}}Y_t^{\text{cycle}} \]

\(Y_t^{\text{trend}}\)は長期的な傾向を表し,GDPであれば経済成長を捉えている。また,トレンドが右上がりでないものありえる。例えば,失業率の場合,自然失業率が一定であればトレンドはないということになる。一方,\(Y_t^{\text{cycle}}\)は短期的な景気循環を捉えている。内閣府は景気循環を「山」と「谷」の2つに分けて景気基準日付を発表している。トレンドを上回っている期間を「山」,下回っている期間を「谷」と考えて良いだろう。図示すると次のようになる。

Hide code cell source
def trend_cycle():
    
    import matplotlib.pyplot as plt
    import matplotlib.lines as mlines
    
    # フォントのサイズ
    font_largest=30
    font_large=20

    # GDPのプロット
    xlow = 0
    xhigh = 3*np.pi
    x = np.arange(xlow, xhigh, 0.1)

    def yfunc(x):
        return np.cos(x+np.pi/2)+0.1*x

    fig, ax = plt.subplots(figsize=(10,5))
    ax.plot(x, yfunc(x), linewidth=7, label='GDP')

    # トレンド線のプロット
    xx = np.linspace(xlow-1., xhigh+1)

    def trend_line(x):
        return ( yfunc(3*np.pi)-yfunc(0) )/(3*np.pi) * (x-0)+yfunc(0)

    ax.plot(xx, trend_line(xx), lw=4, color='orange', label='トレンド')

    # 縦点線のプロット
    ylow = -1.68
    
    tani0 = mlines.Line2D([np.pi/2, np.pi/2], [ylow, yfunc(np.pi/2)],  linestyle='--')
    yama = mlines.Line2D([np.pi*3/2, np.pi*3/2], [ylow+0.4, yfunc(np.pi*3/2)],  linestyle='--')
    tani1 = mlines.Line2D([np.pi*5/2, np.pi*5/2], [ylow, yfunc(np.pi*5/2)],  linestyle='--')
    
    ax.add_line(tani0)
    ax.add_line(yama)
    ax.add_line(tani1)

    # 矢印のプロット(拡張と後退)
    for dx in [np.pi/2, -np.pi/2]:
        ax.arrow(x=np.pi, y=-1.2, dx=dx, dy=0,
                 width=0.01, head_width=0.1,head_length=0.2,
                 length_includes_head=True,color='k')

    for dx in [np.pi/2, -np.pi/2]:
        ax.arrow(x=2*np.pi, y=-1.2, dx=dx, dy=0,
                 width=0.01, head_width=0.1,head_length=0.2,
                 length_includes_head=True,color='k')

    # 矢印のプロット(全循環)
    start_arrow_shift = 0.8
    ax.arrow(x=np.pi*3/2-start_arrow_shift, y=-1.5,
             dx=-(np.pi-start_arrow_shift), dy=0,
             width=0.01, head_width=0.1,head_length=0.2,
             length_includes_head=True,color='k')
    ax.arrow(x=np.pi*3/2+start_arrow_shift, y=-1.5,
             dx=np.pi-start_arrow_shift, dy=0,
             width=0.01, head_width=0.1,head_length=0.2,
             length_includes_head=True,color='k')

    # 注釈の挿入
    x0 = np.pi/2
    x1 = np.pi*3/2
    x2 = np.pi*5/2
    xshift = 0.33
    yshift = 0.2

    ax.annotate('谷', xy=(x0-xshift, yfunc(x0)+yshift),size=font_largest)
    ax.annotate('山', xy=(x1-xshift, yfunc(x1)+yshift), annotation_clip=False, size=font_largest)
    ax.annotate('谷', xy=(x2-xshift, yfunc(x2)+yshift),size=font_largest)

#     ax.annotate('好況', xy=(xlow-1.1,0.2), annotation_clip=False, size=font_large, color='green')
#     ax.annotate('不況', xy=(xlow-1.1,-0.5), annotation_clip=False, size=font_large, color='red')
#     ax.annotate('好況', xy=(xhigh+0.3,1.25), annotation_clip=False, size=font_large, color='green')
#     ax.annotate('不況', xy=(xhigh+0.3,0.55), annotation_clip=False, size=font_large, color='red')

    ax.annotate('拡張', xy=(np.pi-0.2,-1.05), size=font_large, color='green')
    ax.annotate('後退', xy=(2*np.pi-0.5,-1.05), size=font_large, color='red')
    ax.annotate('全循環', xy=(np.pi*3/2-0.65,-1.6), size=font_large)

    # 横軸のラベル,凡例を追加,縦軸の表示範囲の設定
    ax.set_xlabel('時間', size=font_large)
    ax.legend(loc='upper left', fontsize=20)
    ax.set_ylim(ymax=2.3)

    # 縦軸・横軸のラベルと目盛の削除
    ax.set_yticklabels([])
    ax.set_xticklabels([])
    ax.set_xticks([])
    ax.set_yticks([])

    # 枠を削除
    for s in ['top', 'right', 'left','bottom']:
        ax.spines[s].set_visible(False)

trend_cycle()
_images/2c4675b8809431a5a05d0847545c881f730c97dc67b8aee2a46bd7fa4395750b.png

この図のトレンドは右上がりとなっているが,一定もしくは右下がりになる場合もありえる。この図から,拡張・後退はGDPの変化を捉えていることが分かる。また,このプロットはNumPyのコサイン関数を使って描画しているので,「谷」と「山」が発生した時期を簡単に見分けることができる。しかし,上のGDPデータのプロットを見直すと,「谷」と「山」がいつだったかを決めるのは簡単な問題ではないと想像できるだろう。実際,内閣府は単にGDPのデータを眺めるだけではなく景気動向指数を含め様々なデータに基づき,「谷」と「山」の時期を確定している。

景気循環を考える上で重要な役割を果たすのがトレンドである。トレンドはどのように計算するのだろうか。実は,決まった計算方法があるわけではなく,いろいろな考え方がある。実際,内閣府と日本銀行は独自の方法でGDPトレンドを算出している。

  • 内閣府のデータ

    • 「潜在GDP」がトレンドに対応しており,「GDPギャップ」はトレンドからの%乖離を表している。

  • 日本銀行のデータ

    • 「潜在成長率」はトレンドの成長率に対応しており,「需給ギャップ」がトレンドからの%乖離を表している。

いずれにしろ,どのようにトレンドを決めたとしても,景気循環が人々の厚生に大きな影響を及ぼすことには変わりはない。不況は失業や様々な社会問題(例えば,犯罪や自殺)につながる。好況でも問題が無いわけではない。例えば,高いインフレが発生し資産価値(例えば,貨幣)が暴落し通常の生活に支障が出ることもある。またバブル景気が示すように「山」は次の「谷」の芽を育む期間となりえる。

以下では,データを使い景気循環\(Y_t^{\text{cycle}}\)の特徴を調べるが,まず上の式(100)を対数化し次式に書き換える。

(101)#\[ y_t^{\text{cycle}}=y_t-y_t^{\text{trend}} \]

ここで小文字は大文字の変数を対数化した値である(例えば,\(y_t\equiv\log(Y_t)\))。\(y_t^{\text{cycle}}\)をより直感的に解釈するために式(101)の右辺を次のように近似しよう。

(102)#\[ y_t^{\text{cycle}}\approx\dfrac{Y_t-Y_t^{\text{trend}}}{Y_t^{\text{trend}}} \]

即ち,\(y_t^{\text{cycle}}\)は変数\(Y_t\)のトレンドからの乖離をパーセンテージで表している。

ここまでの説明から,景気循環を捉える項\(y_t^{\text{cycle}}\)は変数の値とトレンドとの残差によって決まることがわかる。換言すると,景気循環の特徴はトレンドをどのように考えるかに依存しており,トレンドの算出方法をどうするか決めるかが重要なポイントとなる。ここでは,内閣府や日本銀行の複雑な手法ではなく,マクロ経済学研究でスタンダードなツールとなっているHodrick–Prescottフィルターと呼ばれる手法を使うことにする。詳細についての説明は控え,単にpy4macroに含まれる関数trendを使ってトレンド抽出を行うことにする。使い方は次のコードで確認できる。

help(py4macro.trend)
Help on function trend in module py4macro.py4macro:

trend(s, lamb=1600)
    |
    | 引数:
    |     s: Seriesもしくは1列のDataFrameとし,行のラベルはDatetimeIndexとすること。
    |     lamb: 四半期用のデータでは通常の値(デフォルト:1600)
    |
    | 返り値:
    |     Hodrick-Prescott filterで計算したtrend(トレンド)のSeries
    |
    | 例: py4macro.trend(df.loc[:,'gdp'])

使い方は簡単で,トレンドを計算したい変数のSeriesもしくは1列のDataFrameを引数に設定し実行するとトレンドが返される。ただ,HPフィルターは線形トレンドが仮定されているため,次の点に注意すること。

  • GDPや消費の様に長期的に増加している変数は対数化し,trend()関数の引数に使うこと。

  • 失業率やインフレ率の様に長期的には「一定」になる変数は,そのままtrend()関数の引数に使うこと。

まず次の変数の対数化した変数とそのトレンドを計算しdfに追加しよう。

var_list = ['gdp',
            'consumption',
            'investment',
            'government',
            'exports',
            'imports']
for v in var_list:
    df[v+'_log'] = np.log( df.loc[:,v] )  #1
    df[v+'_log_trend'] = py4macro.trend( df.loc[:,v+'_log'] )  #2

dfの属性.columnsを使い,列ラベルを表示して確認してみよう。

df.columns
Index(['gdp', 'consumption', 'investment', 'government', 'exports', 'imports',
       'capital', 'employed', 'unemployed', 'unemployment_rate', 'hours',
       'total_hours', 'inflation', 'price', 'deflator', 'gdp_log',
       'gdp_growth_quarter', 'gdp_growth_annual', 'gdp_log_trend',
       'consumption_log', 'consumption_log_trend', 'investment_log',
       'investment_log_trend', 'government_log', 'government_log_trend',
       'exports_log', 'exports_log_trend', 'imports_log', 'imports_log_trend'],
      dtype='object')

_log_log_trendが追加された変数が新たに作られていることが確認できる。

GDP#

対数化したGDPの変数を作成しトレンドと重ねて図示してみる。

df[['gdp_log','gdp_log_trend']].plot()
pass
_images/ba76cc871c5b6a984e6f207b95ebc488955a5d32c69e9dbdd0059bd81dabcc23.png

トレンドは直線ではなくスムーズな曲線となっている。上下に動く変数を平滑化したものがトレンドなので直線になるとは限らないのである。

次に景気循環の変数を作成するが,トレンドからの乖離を%で表すために次の関係を利用する。

(103)#\[ \frac{X-Z}{Z} \approx\log\left(\frac{X}{Z}\right) =\log(X) - \log(Z) \]
df['gdp_cycle'] = 100 * ( df['gdp_log'] - df['gdp_log_trend'] )

0に横線を引いてプロットしてみよう。

ax_ = df['gdp_cycle'].plot(marker='.',    # 1
                           linestyle=':',
                           title='GDPのトレンドからの%乖離')
ax_.axhline(0, color='red')               # 2
pass
_images/dcd0ad27b9b81de0e9b0a88ffbd1dcac08a028dc2f711dafc3286546c03fc869.png

図の景気循環はトレンドからの乖離である。乖離の典型的な特徴として持続性がある。これは同じ方向の乖離が続く傾向があるという意味である。即ち,今期景気が良ければ(悪ければ)来期も景気が良い(悪い)可能性が高いということである。もちろん,いずれは乖離が狭まり「山」から「谷」,そして「山」へと循環して行く。持続性を示す数値として自己相関係数がある。

説明するために2つの変数\(Y\)\(Z\)を考え次の係数を定義しよう。

(104)#\[ R(Y,Z)= \frac{ \text{YとZの標本共分散} }{ \sqrt{\text{Yの標本分散}} \sqrt{\text{Xの標本分散}} } \]
  • 分子の標本共分散が符号を決定する。

  • 分母は\(R(Y,Z)\)の値が\(-1\leq R(Y,Z)\leq 1\)となるよう標準化している。

\(t\)期のGDPを\(x_t\)としよう。式(104)を使うと,\(Y\)\(Z\)が次の場合に\(x_t\)の自己相関係数となる。

(105)#\[ Y=x_t,\quad Z=x_{t-1} \]

直感的に説明すると,自己相関とは今期の値が前期の値に依存する程度をいう。前期の影響が強ければ,自己相関係数の絶対値は大きくなる。

(105)として式(104)を計算するが,Seriesにはそれを計算するメソッド.autocorr()が用意されている。

df['gdp_cycle'].autocorr()
0.680888809545929

正の値であり,今期に高(低)ければ来期も高い(低い)可能性が非常に大きいことが分かる。第二の特徴として,「山」と「谷」の形,幅(期間),高さ(深さ)はまちまちであり,不確実な要素の働きが大きい。言い換えると,景気循環の予測は非常に難しい。この点は確率変数として捉えることができるが,このアプローチは後のトピックで扱う。

GDPの構成要素#

トレンドからの乖離#

次にGDPの構成要素について考えるが,まずトレンドからの乖離の変数を作成する(単位:%)。

for v in var_list[1:]:   # gdp以外の変数    
    df[v+'_cycle'] = 100 * ( df[v+'_log'] -df[v+'_log_trend'] ) 

図示する変数のリスを作成するために,列ラベルを確認しよう。

df.columns
Index(['gdp', 'consumption', 'investment', 'government', 'exports', 'imports',
       'capital', 'employed', 'unemployed', 'unemployment_rate', 'hours',
       'total_hours', 'inflation', 'price', 'deflator', 'gdp_log',
       'gdp_growth_quarter', 'gdp_growth_annual', 'gdp_log_trend',
       'consumption_log', 'consumption_log_trend', 'investment_log',
       'investment_log_trend', 'government_log', 'government_log_trend',
       'exports_log', 'exports_log_trend', 'imports_log', 'imports_log_trend',
       'gdp_cycle', 'consumption_cycle', 'investment_cycle',
       'government_cycle', 'exports_cycle', 'imports_cycle'],
      dtype='object')

列ラベルに_cycleがついている変数だけを選ぶためにcycle_listを作成する。

cycle_list = df.columns[-6:]   # 最後の6変数

df.loc[:,cycle_list].plot(subplots=True, figsize=(8,10))
pass
_images/b755aa148f1b77581b7480dda99eb802b5e642600af3f7522abc1cf15eaca8d6.png

この図に基づいて3つの点について考える。

  1. 持続性を示す自己相関

  2. GDPと順循環的(pro-cyclical)か反循環的(counter- cyclical)かどうか

  3. 変動の大きさの比較

自己相関#

forループを使って自己相関係数を計算しよう。

for v in cycle_list:
    autocorr = df[v].autocorr()           # (1)
    print(f'{v:<19}{autocorr:>5.2f}')     # (2)
gdp_cycle           0.68
consumption_cycle   0.46
investment_cycle    0.84
government_cycle    0.63
exports_cycle       0.74
imports_cycle       0.82

全て0.45以上であり,強い持続性が確認できる。

GDPとの相関度#

GDPと他の変数との相関度を確認するために2変数の相関係数を考えよう。式(104)を使うと\(Y\)\(Z\)は次のようになる。

(106)#\[ Y=\text{GDP},\quad Z=\text{GDPの構成要素の変数} \]

(106)として式(104)を計算するが,Seriesにはそれを計算するメソッド.corr()が用意されている。forループを使って計算しよう。

print('GDPの変動との相関係数\n------------------------')

for v in cycle_list:
    corr = df[['gdp_cycle', v]].corr().iloc[0,1]  # 1
    print(f'{v:<19}{corr:>5.2f}')                 # 2
GDPの変動との相関係数
------------------------
gdp_cycle           1.00
consumption_cycle   0.77
investment_cycle    0.77
government_cycle   -0.15
exports_cycle       0.75
imports_cycle       0.66

政府支出以外は全て相関係数は正の値であり,値も大きい。即ち,順循環的である(裏にあるメカニズムを考えてみよう)。下の図はGDPと投資の散布図であり,正の相関を確認できる。

df.plot('gdp_cycle', 'investment_cycle', kind='scatter')
pass
_images/71b25ed5f30aac05f4f952d4e041883fee18bf6703b2ae5b8072f6d9db914079.png

一方,政府支出の値は負であり,景気循環をコントロールしようとする政府の政策の現れと解釈できる。値が小さいのは,時間的なラグがあるためだと思われる。景気に関するデータを集計するには数ヶ月かかり,国会審議や支出の実行にも時間を取られることになる。時間的なラグを捉えるために,Seriesのメソッド.shift()を使って相関係数を再計算してみよう。

print('  GDPとの相関係数\n-----------------------')

for n in range(1,12):
    
    df['gov_cycle_shift'] = df['government_cycle'].shift(-n)     #1
    
    corr = df[['gdp_cycle', 'gov_cycle_shift']].corr().iloc[0,1]
    
    print(f'{n:>3}期先の政府支出: {corr:>6.3f}')
    
    del df['gov_cycle_shift']                                    #2
  GDPとの相関係数
-----------------------
  1期先の政府支出: -0.304
  2期先の政府支出: -0.380
  3期先の政府支出: -0.365
  4期先の政府支出: -0.274
  5期先の政府支出: -0.212
  6期先の政府支出: -0.099
  7期先の政府支出: -0.037
  8期先の政府支出:  0.055
  9期先の政府支出:  0.092
 10期先の政府支出:  0.118
 11期先の政府支出:  0.119

GDPの乖離は2四半期先の政府支出との相関係数が最大となっている。景気循環に対する政府の姿勢が確認できる一方,政府の対応には長いの時間が掛かることを示す結果となっている。

変動の大きさ#

次に変動の大きさを考えるために,GDPの標準偏差に対するそれぞれの構成要素の標準偏差の比率を計算する。

for v in cycle_list:
    var = df[v].std() / df['gdp_cycle'].std()
    print(f'{v:<19}{var:>5.2f}')
gdp_cycle           1.00
consumption_cycle   0.81
investment_cycle    3.19
government_cycle    0.90
exports_cycle       3.83
imports_cycle       3.30

投資,輸出,輸入の値はGDPの3倍以上であり,政府支出の値はGDPより低く,消費の変動は更に小さい。これは消費者の不確実性を嫌う姿勢が反映されていると解釈できる。GDPの構成要素を対GDP比率で検討した際,消費は投資よりも比率が大きかったことを思い出そう。変動に関しては,順位が逆転し投資が大きく上回っている。この点を図示して視覚的に確認してみよう。

df.loc[:,cycle_list[:3]].plot()
pass
_images/b4a2d46797db112469f51a68418a314cf6371971b8c6f700b76784cad1d9f956.png

これらの結果を説明するために,効用最大化に基づく消費者理論があり,利潤最大化に基づく企業行動に関するモデルが使われている。