Time Series Forecasting - Box-Jekins Methon (ARIMA) in Python and

Time Series Forecasting - FBProphet in Python

Bangladesh Inflation - Consumer Price Annual Percentage Forecasting

In [3]:
# ignore warnings
import pandas as pd
import warnings
warnings.filterwarnings("ignore")

Load dataset

In [4]:
# load dataset
from pandas import read_csv
from pandas import datetime
from matplotlib import pyplot
from pandas.plotting import autocorrelation_plot

filename = 'Bangladesh_Inflation_ConsumerPriceData_Annual_percentages.csv'

df = read_csv(filename)
df = df.set_index('Year')

df.plot(figsize = (8,6))

fig = pyplot.figure(figsize = (8,6))
autocorrelation_plot(df)
pyplot.show()

print(df.head(5))
      Inflation_ConsumerPrice_Annual_Percentage
Year                                           
1987                                   9.874696
1988                                   7.412766
1989                                   6.045480
1990                                   6.126718
1991                                   6.357364

Autocorrelation and Partial Autocorrelation in Python

In [5]:
from statsmodels.graphics.tsaplots import plot_acf
import matplotlib.pyplot as plt

plt.rcParams.update({'figure.figsize':(6,4), 'figure.dpi':120})

plot_acf(df)
pyplot.show()
In [6]:
from statsmodels.graphics.tsaplots import plot_pacf

plot_pacf(df)
pyplot.show()

ADF test

In [7]:
from statsmodels.tsa.stattools import adfuller

# ADF Test
def adf_test(series):
    result = adfuller(series, autolag='AIC')
    print(); print(f'ADF Statistic: {result[0]}')
    print();  print(f'n_lags: {result[1]}')
    print();  print(f'p-value: {result[1]}')

    print(); print('Critial Values:')
    for key, value in result[4].items():
        print(f'   {key}, {value}')   

adf_test(df["Inflation_ConsumerPrice_Annual_Percentage"])
ADF Statistic: -2.271393511769288

n_lags: 0.18136015289656765

p-value: 0.18136015289656765

Critial Values:
   1%, -3.661428725118324
   5%, -2.960525341210433
   10%, -2.6193188033298647

KPSS Test

In [8]:
from statsmodels.tsa.stattools import kpss

def kpss_test(series, **kw):    
    
    statistic, p_value, n_lags, critical_values = kpss(series, **kw)
    
    # Format Output
    print(); print(f'KPSS Statistic: {statistic}')
    print(); print(f'p-value: {p_value}')
    print(); print(f'num lags: {n_lags}')
    print(); print('Critial Values:')
    for key, value in critical_values.items():
        print(f'   {key} : {value}')
    
kpss_test(df["Inflation_ConsumerPrice_Annual_Percentage"])
KPSS Statistic: 0.12841083906112724

p-value: 0.1

num lags: 10

Critial Values:
   10% : 0.347
   5% : 0.463
   2.5% : 0.574
   1% : 0.739
/home/crown/miniconda/envs/nilimeshdss/lib/python3.6/site-packages/statsmodels/tsa/stattools.py:1278: InterpolationWarning: p-value is greater than the indicated p-value
  warn("p-value is greater than the indicated p-value", InterpolationWarning)

How to find the order of differencing (d) in ARIMA model

In [9]:
import numpy as np, pandas as pd
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt
plt.rcParams.update({'figure.figsize':(12,14), 'figure.dpi':120})

# Import data
#df = pd.read_csv('shampoo.csv', header=0, names = ['Sales'])
df.reset_index(drop=True, inplace=True)

# Original Series
fig, axes = plt.subplots(5, 2, sharex=True)
axes[0, 0].plot(df.values); axes[0, 0].set_title('Original Series')
plot_acf(df.values, ax=axes[0, 1])

# 1st Differencing
df1 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff()
axes[1, 0].plot(df1); axes[1, 0].set_title('1st Order Differencing')
plot_acf(df1.dropna(), ax=axes[1, 1])

# 2nd Differencing
df2 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff().diff()
axes[2, 0].plot(df2); axes[2, 0].set_title('2nd Order Differencing')
plot_acf(df2.dropna(), ax=axes[2, 1])

# 3rd Differencing
df3 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff().diff().diff()
axes[3, 0].plot(df3); axes[3, 0].set_title('3rd Order Differencing')
plot_acf(df3.dropna(), ax=axes[3, 1])

# 3rd Differencing
df4 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff().diff().diff().diff()
axes[4, 0].plot(df4); axes[4, 0].set_title('4th Order Differencing')
plot_acf(df4.dropna(), ax=axes[4, 1])

plt.show()

ADF and KPSS statistics

In [10]:
warnings.filterwarnings("ignore")

print("---------------------------------------------")
print("First Diffencing: ")
print("---------------------------------------------")
df1 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff()
print(); print("---------------------------------------------")
adf_test(df1.dropna())
print(); print("---------------------------------------------")
kpss_test(df1.dropna())
print(); print("---------------------------------------------")


print(); print("---------------------------------------------")
print("2nd Diffencing: ")
print("---------------------------------------------")
df2 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff().diff()
print(); print("---------------------------------------------")
adf_test(df2.dropna())
print(); print("---------------------------------------------")
kpss_test(df2.dropna())
print(); print("---------------------------------------------")

print(); print("---------------------------------------------")
print("3rd Diffencing: ")
print("---------------------------------------------")
df3 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff().diff().diff()
print(); print("---------------------------------------------")
adf_test(df3.dropna())
print(); print("---------------------------------------------")
kpss_test(df3.dropna())
print(); print("---------------------------------------------")

print(); print("---------------------------------------------")
print("4th Diffencing: ")
print("---------------------------------------------")
df4 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff().diff().diff().diff()
print(); print("---------------------------------------------")
adf_test(df4.dropna())
print(); print("---------------------------------------------")
kpss_test(df4.dropna())
print(); print("---------------------------------------------")
---------------------------------------------
First Diffencing: 
---------------------------------------------

---------------------------------------------

ADF Statistic: -7.5080263631658255

n_lags: 4.0852802984359826e-11

p-value: 4.0852802984359826e-11

Critial Values:
   1%, -3.661428725118324
   5%, -2.960525341210433
   10%, -2.6193188033298647

---------------------------------------------

KPSS Statistic: 0.18141599308858564

p-value: 0.1

num lags: 10

Critial Values:
   10% : 0.347
   5% : 0.463
   2.5% : 0.574
   1% : 0.739

---------------------------------------------

---------------------------------------------
2nd Diffencing: 
---------------------------------------------

---------------------------------------------

ADF Statistic: -7.8044920143602114

n_lags: 7.343229016783875e-12

p-value: 7.343229016783875e-12

Critial Values:
   1%, -3.6790595944893187
   5%, -2.9678817237279103
   10%, -2.6231583472057074

---------------------------------------------

KPSS Statistic: 0.15579213314782414

p-value: 0.1

num lags: 10

Critial Values:
   10% : 0.347
   5% : 0.463
   2.5% : 0.574
   1% : 0.739

---------------------------------------------

---------------------------------------------
3rd Diffencing: 
---------------------------------------------

---------------------------------------------

ADF Statistic: -3.8726336804525343

n_lags: 0.002245738295286738

p-value: 0.002245738295286738

Critial Values:
   1%, -3.769732625845229
   5%, -3.005425537190083
   10%, -2.6425009917355373

---------------------------------------------

KPSS Statistic: 0.1683985451344656

p-value: 0.1

num lags: 9

Critial Values:
   10% : 0.347
   5% : 0.463
   2.5% : 0.574
   1% : 0.739

---------------------------------------------

---------------------------------------------
4th Diffencing: 
---------------------------------------------

---------------------------------------------

ADF Statistic: -4.212752861770608

n_lags: 0.0006269029244020249

p-value: 0.0006269029244020249

Critial Values:
   1%, -3.8092091249999998
   5%, -3.0216450000000004
   10%, -2.6507125

---------------------------------------------

KPSS Statistic: 0.17839273327677874

p-value: 0.1

num lags: 9

Critial Values:
   10% : 0.347
   5% : 0.463
   2.5% : 0.574
   1% : 0.739

---------------------------------------------
In [ ]:
 

How to find the order of the AR term (p)

In [11]:
from statsmodels.graphics.tsaplots import plot_pacf

# PACF plot 
plt.rcParams.update({'figure.figsize':(9,3), 'figure.dpi':120})
fig, axes = plt.subplots(1, 2, sharex=True)

df2 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff().diff() #.diff() #.diff()

axes[0].plot(df2); axes[0].set_title('2nd Differencing')
axes[1].set(ylim=(-3,3))
plot_pacf(df2.dropna(), ax=axes[1]) #PACF

plt.show()

How to find the order of the MA term (q)

In [12]:
from statsmodels.graphics.tsaplots import plot_acf
import matplotlib.pyplot as plt

plt.rcParams.update({'figure.figsize':(9,3), 'figure.dpi':120})
fig, axes = plt.subplots(1, 2, sharex=True)

df2 = df["Inflation_ConsumerPrice_Annual_Percentage"].diff().diff() #.diff() #.diff()
axes[0].plot(df2); axes[0].set_title('2nd Differencing')
#axes[1].set(ylim=(0,1.2))
plot_acf(df2.dropna(), ax=axes[1]) # ACF

plt.show()
In [13]:
## ADF test
adf_test(df2.dropna())
ADF Statistic: -7.8044920143602114

n_lags: 7.343229016783875e-12

p-value: 7.343229016783875e-12

Critial Values:
   1%, -3.6790595944893187
   5%, -2.9678817237279103
   10%, -2.6231583472057074

Build the ARIMA(p,d,q) Model

In [14]:
from statsmodels.tsa.arima_model import ARIMA

plt.rcParams.update({'figure.figsize':(16,6), 'figure.dpi':220})

df = read_csv(filename)
df = df.set_index('Year')

# ARIMA Model
model = ARIMA(df["Inflation_ConsumerPrice_Annual_Percentage"], order=(2,2,0))
model_fit = model.fit(disp=0)
print(model_fit.summary())

# Plot residual errors
residuals = pd.DataFrame(model_fit.resid)
fig, ax = plt.subplots(1,2)
residuals.plot(title="Residuals", ax=ax[0])
residuals.plot(kind='kde', title='Density', ax=ax[1])
plt.show()

# Actual vs Fitted
model_fit.plot_predict(dynamic=False)
plt.show()
                                          ARIMA Model Results                                           
========================================================================================================
Dep. Variable:     D2.Inflation_ConsumerPrice_Annual_Percentage   No. Observations:                   32
Model:                                           ARIMA(2, 2, 0)   Log Likelihood                 -80.600
Method:                                                 css-mle   S.D. of innovations              2.956
Date:                                          Fri, 30 Jul 2021   AIC                            169.201
Time:                                                  16:10:35   BIC                            175.064
Sample:                                                       2   HQIC                           171.144
                                                                                                        
======================================================================================================================
                                                         coef    std err          z      P>|z|      [0.025      0.975]
----------------------------------------------------------------------------------------------------------------------
const                                                  0.0493      0.236      0.208      0.836      -0.414       0.513
ar.L1.D2.Inflation_ConsumerPrice_Annual_Percentage    -0.6872      0.138     -4.963      0.000      -0.959      -0.416
ar.L2.D2.Inflation_ConsumerPrice_Annual_Percentage    -0.5809      0.133     -4.367      0.000      -0.842      -0.320
                                    Roots                                    
=============================================================================
                  Real          Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
AR.1           -0.5915           -1.1712j            1.3120           -0.3244
AR.2           -0.5915           +1.1712j            1.3120            0.3244
-----------------------------------------------------------------------------
In [ ]:
 

using Auto ARIMA

In [15]:
import pmdarima as pm

model_with_auto_d = pm.auto_arima(df, start_p=1, start_q=1,
                      test='adf',       # use adftest to find optimal 'd'
                      max_p=4, max_q=4, # maximum p, q
                      m=1,              # frequency of series
                      
                      d=None,           # let model determine 'd'
                      
                      seasonal=False,   # No Seasonality
                      start_P=0, 
                      D=0, 
                      trace=True,
                      error_action='ignore',  
                      suppress_warnings=True, 
                      stepwise=True)

print(model_with_auto_d.summary())
Fit ARIMA: order=(1, 2, 1); AIC=nan, BIC=nan, Fit time=nan seconds
Fit ARIMA: order=(0, 2, 0); AIC=185.926, BIC=188.858, Fit time=0.002 seconds
Fit ARIMA: order=(1, 2, 0); AIC=181.361, BIC=185.758, Fit time=0.022 seconds
Fit ARIMA: order=(0, 2, 1); AIC=162.402, BIC=166.800, Fit time=0.061 seconds
Fit ARIMA: order=(0, 2, 2); AIC=nan, BIC=nan, Fit time=nan seconds
Fit ARIMA: order=(1, 2, 2); AIC=nan, BIC=nan, Fit time=nan seconds
Total fit time: 0.109 seconds
                             ARIMA Model Results                              
==============================================================================
Dep. Variable:                   D2.y   No. Observations:                   32
Model:                 ARIMA(0, 2, 1)   Log Likelihood                 -78.201
Method:                       css-mle   S.D. of innovations              2.639
Date:                Fri, 30 Jul 2021   AIC                            162.402
Time:                        16:10:37   BIC                            166.800
Sample:                             2   HQIC                           163.860
                                                                              
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          0.0173      0.048      0.359      0.722      -0.077       0.112
ma.L1.D2.y    -1.0000      0.083    -12.081      0.000      -1.162      -0.838
                                    Roots                                    
=============================================================================
                  Real          Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
MA.1            1.0000           +0.0000j            1.0000            0.0000
-----------------------------------------------------------------------------
In [16]:
model_with_d_equals_1 = pm.auto_arima(df, start_p=1, start_q=1,
                      test='adf',       # use adftest to find optimal 'd'
                      max_p=4, max_q=4, max_d=4, # maximum p, q and d
                      m=1,              # frequency of series
                      
                      d=1,              # let model determine 'd'
                      
                      seasonal=False,   # No Seasonality
                      start_P=0, 
                      D=0, 
                      trace=True,
                      error_action='ignore',  
                      suppress_warnings=True, 
                      stepwise=True)

print(model_with_d_equals_1.summary())
Fit ARIMA: order=(1, 1, 1); AIC=154.753, BIC=160.739, Fit time=0.043 seconds
Fit ARIMA: order=(0, 1, 0); AIC=160.801, BIC=163.794, Fit time=0.002 seconds
Fit ARIMA: order=(1, 1, 0); AIC=160.749, BIC=165.238, Fit time=0.011 seconds
Fit ARIMA: order=(0, 1, 1); AIC=155.203, BIC=159.692, Fit time=0.015 seconds
Fit ARIMA: order=(2, 1, 1); AIC=154.777, BIC=162.259, Fit time=0.044 seconds
Fit ARIMA: order=(1, 1, 2); AIC=155.317, BIC=162.800, Fit time=0.089 seconds
Fit ARIMA: order=(2, 1, 2); AIC=155.704, BIC=164.683, Fit time=0.083 seconds
Total fit time: 0.288 seconds
                             ARIMA Model Results                              
==============================================================================
Dep. Variable:                    D.y   No. Observations:                   33
Model:                 ARIMA(1, 1, 1)   Log Likelihood                 -73.377
Method:                       css-mle   S.D. of innovations              2.141
Date:                Fri, 30 Jul 2021   AIC                            154.753
Time:                        16:10:38   BIC                            160.739
Sample:                             1   HQIC                           156.767
                                                                              
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          0.0065      0.055      0.119      0.906      -0.101       0.114
ar.L1.D.y      0.3364      0.179      1.878      0.070      -0.015       0.688
ma.L1.D.y     -1.0000      0.099    -10.107      0.000      -1.194      -0.806
                                    Roots                                    
=============================================================================
                  Real          Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
AR.1            2.9723           +0.0000j            2.9723            0.0000
MA.1            1.0000           +0.0000j            1.0000            0.0000
-----------------------------------------------------------------------------
In [17]:
model_with_d_equals_2 = pm.auto_arima(df, start_p=1, start_q=1,
                      test='adf',       # use adftest to find optimal 'd'
                      max_p=4, max_q=4, # maximum p, q
                      m=1,              # frequency of series
                      
                      d=2,              # let model determine 'd'
                      
                      seasonal=False,   # No Seasonality
                      start_P=0, 
                      D=0, 
                      trace=True,
                      error_action='ignore',  
                      suppress_warnings=True, 
                      stepwise=True)

print(model_with_d_equals_2.summary())
Fit ARIMA: order=(1, 2, 1); AIC=nan, BIC=nan, Fit time=nan seconds
Fit ARIMA: order=(0, 2, 0); AIC=185.926, BIC=188.858, Fit time=0.002 seconds
Fit ARIMA: order=(1, 2, 0); AIC=181.361, BIC=185.758, Fit time=0.013 seconds
Fit ARIMA: order=(0, 2, 1); AIC=162.402, BIC=166.800, Fit time=0.056 seconds
Fit ARIMA: order=(0, 2, 2); AIC=nan, BIC=nan, Fit time=nan seconds
Fit ARIMA: order=(1, 2, 2); AIC=nan, BIC=nan, Fit time=nan seconds
Total fit time: 0.091 seconds
                             ARIMA Model Results                              
==============================================================================
Dep. Variable:                   D2.y   No. Observations:                   32
Model:                 ARIMA(0, 2, 1)   Log Likelihood                 -78.201
Method:                       css-mle   S.D. of innovations              2.639
Date:                Fri, 30 Jul 2021   AIC                            162.402
Time:                        16:10:38   BIC                            166.800
Sample:                             2   HQIC                           163.860
                                                                              
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          0.0173      0.048      0.359      0.722      -0.077       0.112
ma.L1.D2.y    -1.0000      0.083    -12.081      0.000      -1.162      -0.838
                                    Roots                                    
=============================================================================
                  Real          Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
MA.1            1.0000           +0.0000j            1.0000            0.0000
-----------------------------------------------------------------------------

How to interpret the residual plots in ARIMA model

In [18]:
model_with_auto_d.plot_diagnostics(figsize=(12,10))
plt.show()
In [19]:
model_with_d_equals_1.plot_diagnostics(figsize=(12,10))
plt.show()
In [20]:
model_with_d_equals_2.plot_diagnostics(figsize=(12,10))
plt.show()

Forecast

In [21]:
model = model_with_auto_d
In [22]:
# Forecast
n_periods = 10
fc, confint = model.predict(n_periods=n_periods, return_conf_int=True)
#index_of_fc = np.arange(len(df), len(df)+n_periods)
index_of_fc = np.arange(2020, 2020+n_periods)

# make series for plotting purpose
fc_series = pd.Series(fc, index=index_of_fc)
lower_series = pd.Series(confint[:, 0], index=index_of_fc)
upper_series = pd.Series(confint[:, 1], index=index_of_fc)

# Plot
plt.plot(df)
plt.plot(fc_series, color='darkgreen')
plt.fill_between(lower_series.index, 
                 lower_series, 
                 upper_series, 
                 color='k', alpha=.15)

plt.title("Final Forecast")
plt.show()

print(); print(fc_series)
print(); print(lower_series)
print(); print(upper_series)
2020    5.860225
2021    6.046689
2022    6.250467
2023    6.471557
2024    6.709962
2025    6.965680
2026    7.238712
2027    7.529057
2028    7.836715
2029    8.161688
dtype: float64

2020    0.688723
2021   -1.267063
2022   -2.707190
2023   -3.872057
2024   -4.854779
2025   -5.703108
2026   -6.445413
2027   -7.100176
2028   -7.680235
2029   -8.194936
dtype: float64

2020    11.031727
2021    13.360441
2022    15.208123
2023    16.815172
2024    18.274703
2025    19.634469
2026    20.922837
2027    22.158290
2028    23.353666
2029    24.518312
dtype: float64

Using FB Prophet

In [23]:
from fbprophet import Prophet
import pandas as pd

df = read_csv(filename)
#df = df.set_index('Year')

print(df.head())
#print(); print(df[['Year', 'Population']])

df["End_Year"] = 0
for i in range(0, len(df)):
    df.iloc[i, 2] = str(df.iloc[i, 0]) + '-12-' + '31'

print(); print(df.head())
   Year  Inflation_ConsumerPrice_Annual_Percentage
0  1987                                   9.874696
1  1988                                   7.412766
2  1989                                   6.045480
3  1990                                   6.126718
4  1991                                   6.357364

   Year  Inflation_ConsumerPrice_Annual_Percentage    End_Year
0  1987                                   9.874696  1987-12-31
1  1988                                   7.412766  1988-12-31
2  1989                                   6.045480  1989-12-31
3  1990                                   6.126718  1990-12-31
4  1991                                   6.357364  1991-12-31
In [24]:
# Create a new Data Frame
df_pop = pd.DataFrame()

df_pop[['ds','y']] = df[['End_Year', 'Inflation_ConsumerPrice_Annual_Percentage']]

# Convert Data Frame to FBProphet Timeseries ds and y
df_pop['ds'] = pd.to_datetime(df_pop['ds'])
df_pop['y']  = pd.to_numeric(df_pop['y'])

print(df_pop.tail())

# Create FBProphet Model with Dataset
m = Prophet(daily_seasonality=False, weekly_seasonality=True, yearly_seasonality=True)
m.fit(df_pop)

future = m.make_future_dataframe(periods=10, freq = 'Y')

print()
print(future.tail(26))

forecast = m.predict(future)
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(25))

fig = m.plot(forecast)
plt.show()


# Save Data in a CSV file
df_final = pd.DataFrame()
df_final[['Year', 'yhat', 'yhat_lower', 'yhat_upper']] = forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']]

df_final['Inflation_ConsumerPrice_Annual_Percentage'] = df_pop['y']

print(df_final.head(len(df_final)))

#df_final.to_csv('Forecast_final.csv',index = False)
           ds         y
29 2016-12-31  5.513526
30 2017-12-31  5.702070
31 2018-12-31  5.543621
32 2019-12-31  5.591996
33 2020-12-31  5.691075

           ds
18 2005-12-31
19 2006-12-31
20 2007-12-31
21 2008-12-31
22 2009-12-31
23 2010-12-31
24 2011-12-31
25 2012-12-31
26 2013-12-31
27 2014-12-31
28 2015-12-31
29 2016-12-31
30 2017-12-31
31 2018-12-31
32 2019-12-31
33 2020-12-31
34 2021-12-31
35 2022-12-31
36 2023-12-31
37 2024-12-31
38 2025-12-31
39 2026-12-31
40 2027-12-31
41 2028-12-31
42 2029-12-31
43 2030-12-31
           ds      yhat  yhat_lower  yhat_upper
19 2006-12-31  6.836826    4.300551    9.218819
20 2007-12-31  7.171531    4.882218    9.350331
21 2008-12-31  5.455379    3.056988    7.673872
22 2009-12-31  6.162305    3.878476    8.580901
23 2010-12-31  6.841394    4.554450    9.196654
24 2011-12-31  9.227786    6.948782   11.598830
25 2012-12-31  4.557351    2.453467    6.876939
26 2013-12-31  4.481624    2.095653    6.719854
27 2014-12-31  7.348083    5.172218    9.622883
28 2015-12-31  8.233348    5.823911   10.518635
29 2016-12-31  6.613606    4.294118    9.175927
30 2017-12-31  6.203962    3.851200    8.379553
31 2018-12-31  6.450055    4.165918    8.802860
32 2019-12-31  6.552667    4.187621    8.949262
33 2020-12-31  5.619168    3.328905    7.813238
34 2021-12-31  6.208530    3.986887    8.602547
35 2022-12-31  8.506310    6.437232   10.844639
36 2023-12-31  8.275005    5.990151   10.544351
37 2024-12-31  3.938487    1.389233    6.332452
38 2025-12-31  6.715219    4.615761    9.317595
39 2026-12-31  7.511872    5.242517    9.928722
40 2027-12-31  8.279574    5.895602   10.775780
41 2028-12-31  5.660825    3.371347    7.818098
42 2029-12-31  5.817191    3.357264    7.923483
43 2030-12-31  5.831191    3.498907    8.140303
         Year      yhat  yhat_lower  yhat_upper  \
0  1987-12-31  7.516645    5.360845    9.711015   
1  1988-12-31  5.896903    3.553763    8.350406   
2  1989-12-31  5.487259    3.082573    7.638698   
3  1990-12-31  5.733352    3.395475    8.022517   
4  1991-12-31  5.835964    3.393088    8.123600   
5  1992-12-31  4.902465    2.769438    7.486748   
6  1993-12-31  5.491827    3.085338    7.759117   
7  1994-12-31  7.789607    5.580980   10.172604   
8  1995-12-31  7.558302    5.235041    9.893133   
9  1996-12-31  3.221784    1.000110    5.498073   
10 1997-12-31  5.998516    3.769278    8.324218   
11 1998-12-31  6.795169    4.589272    9.183781   
12 1999-12-31  7.562870    5.415430    9.972285   
13 2000-12-31  4.944122    2.739024    7.106978   
14 2001-12-31  5.100488    2.669567    7.383920   
15 2002-12-31  5.114488    2.974147    7.224225   
16 2003-12-31  8.069559    5.766062   10.464360   
17 2004-12-31  4.948690    2.647924    7.153817   
18 2005-12-31  7.156743    4.819737    9.513348   
19 2006-12-31  6.836826    4.300551    9.218819   
20 2007-12-31  7.171531    4.882218    9.350331   
21 2008-12-31  5.455379    3.056988    7.673872   
22 2009-12-31  6.162305    3.878476    8.580901   
23 2010-12-31  6.841394    4.554450    9.196654   
24 2011-12-31  9.227786    6.948782   11.598830   
25 2012-12-31  4.557351    2.453467    6.876939   
26 2013-12-31  4.481624    2.095653    6.719854   
27 2014-12-31  7.348083    5.172218    9.622883   
28 2015-12-31  8.233348    5.823911   10.518635   
29 2016-12-31  6.613606    4.294118    9.175927   
30 2017-12-31  6.203962    3.851200    8.379553   
31 2018-12-31  6.450055    4.165918    8.802860   
32 2019-12-31  6.552667    4.187621    8.949262   
33 2020-12-31  5.619168    3.328905    7.813238   
34 2021-12-31  6.208530    3.986887    8.602547   
35 2022-12-31  8.506310    6.437232   10.844639   
36 2023-12-31  8.275005    5.990151   10.544351   
37 2024-12-31  3.938487    1.389233    6.332452   
38 2025-12-31  6.715219    4.615761    9.317595   
39 2026-12-31  7.511872    5.242517    9.928722   
40 2027-12-31  8.279574    5.895602   10.775780   
41 2028-12-31  5.660825    3.371347    7.818098   
42 2029-12-31  5.817191    3.357264    7.923483   
43 2030-12-31  5.831191    3.498907    8.140303   

    Inflation_ConsumerPrice_Annual_Percentage  
0                                    9.874696  
1                                    7.412766  
2                                    6.045480  
3                                    6.126718  
4                                    6.357364  
5                                    3.634077  
6                                    3.014819  
7                                    5.313740  
8                                   10.297812  
9                                    2.377129  
10                                   5.305601  
11                                   8.402238  
12                                   6.106696  
13                                   2.208256  
14                                   2.007174  
15                                   3.332565  
16                                   5.668708  
17                                   7.587536  
18                                   7.046618  
19                                   6.765261  
20                                   9.106985  
21                                   8.901945  
22                                   5.423472  
23                                   8.126676  
24                                  11.395165  
25                                   6.217504  
26                                   7.530406  
27                                   6.991639  
28                                   6.194280  
29                                   5.513526  
30                                   5.702070  
31                                   5.543621  
32                                   5.591996  
33                                   5.691075  
34                                        NaN  
35                                        NaN  
36                                        NaN  
37                                        NaN  
38                                        NaN  
39                                        NaN  
40                                        NaN  
41                                        NaN  
42                                        NaN  
43                                        NaN  
In [ ]: