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

Time Series Forecasting - FBProphet in Python

India 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 = 'India_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                                           
1960                                   1.779878
1961                                   1.695213
1962                                   3.632215
1963                                   2.946161
1964                                  13.355261

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: -4.852216353352053

n_lags: 4.316557007564544e-05

p-value: 4.316557007564544e-05

Critial Values:
   1%, -3.552928203580539
   5%, -2.9147306250000002
   10%, -2.595137155612245

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.1348448912120867

p-value: 0.1

num lags: 11

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: -6.358635732953807

n_lags: 2.5062831793258564e-08

p-value: 2.5062831793258564e-08

Critial Values:
   1%, -3.55770911573439
   5%, -2.9167703434435808
   10%, -2.59622219478738

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

KPSS Statistic: 0.12064523777860119

p-value: 0.1

num lags: 11

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

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

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

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

ADF Statistic: -5.770414261078949

n_lags: 5.408760857382343e-07

p-value: 5.408760857382343e-07

Critial Values:
   1%, -3.568485864
   5%, -2.92135992
   10%, -2.5986616

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

KPSS Statistic: 0.09407493047765798

p-value: 0.1

num lags: 11

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

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

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

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

ADF Statistic: -6.250493352039788

n_lags: 4.466457270149089e-08

p-value: 4.466457270149089e-08

Critial Values:
   1%, -3.5812576580093696
   5%, -2.9267849124681518
   10%, -2.6015409829867675

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

KPSS Statistic: 0.10025631122029302

p-value: 0.1

num lags: 11

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

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

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

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

ADF Statistic: -6.625863172453976

n_lags: 5.878738566882934e-09

p-value: 5.878738566882934e-09

Critial Values:
   1%, -3.584828853223594
   5%, -2.9282991495198907
   10%, -2.6023438271604937

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

KPSS Statistic: 0.09866174487254907

p-value: 0.1

num lags: 11

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: -5.770414261078949

n_lags: 5.408760857382343e-07

p-value: 5.408760857382343e-07

Critial Values:
   1%, -3.568485864
   5%, -2.92135992
   10%, -2.5986616

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:                   59
Model:                                           ARIMA(2, 2, 0)   Log Likelihood                -193.911
Method:                                                 css-mle   S.D. of innovations              6.422
Date:                                          Mon, 02 Aug 2021   AIC                            395.821
Time:                                                  17:13:18   BIC                            404.132
Sample:                                                       2   HQIC                           399.065
                                                                                                        
======================================================================================================================
                                                         coef    std err          z      P>|z|      [0.025      0.975]
----------------------------------------------------------------------------------------------------------------------
const                                                  0.0189      0.388      0.049      0.961      -0.741       0.779
ar.L1.D2.Inflation_ConsumerPrice_Annual_Percentage    -0.6219      0.105     -5.907      0.000      -0.828      -0.416
ar.L2.D2.Inflation_ConsumerPrice_Annual_Percentage    -0.5648      0.103     -5.489      0.000      -0.766      -0.363
                                    Roots                                    
=============================================================================
                  Real          Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
AR.1           -0.5506           -1.2114j            1.3306           -0.3179
AR.2           -0.5506           +1.2114j            1.3306            0.3179
-----------------------------------------------------------------------------
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, 0, 1); AIC=361.800, BIC=370.244, Fit time=0.039 seconds
Fit ARIMA: order=(0, 0, 0); AIC=371.239, BIC=375.461, Fit time=0.002 seconds
Fit ARIMA: order=(1, 0, 0); AIC=365.629, BIC=371.961, Fit time=0.016 seconds
Fit ARIMA: order=(0, 0, 1); AIC=360.259, BIC=366.591, Fit time=0.014 seconds
Fit ARIMA: order=(0, 0, 2); AIC=361.670, BIC=370.114, Fit time=0.027 seconds
Fit ARIMA: order=(1, 0, 2); AIC=nan, BIC=nan, Fit time=nan seconds
Total fit time: 0.114 seconds
                              ARMA Model Results                              
==============================================================================
Dep. Variable:                      y   No. Observations:                   61
Model:                     ARMA(0, 1)   Log Likelihood                -177.129
Method:                       css-mle   S.D. of innovations              4.402
Date:                Mon, 02 Aug 2021   AIC                            360.259
Time:                        17:13:20   BIC                            366.591
Sample:                             0   HQIC                           362.741
                                                                              
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          7.4097      0.863      8.585      0.000       5.718       9.101
ma.L1.y        0.5401      0.114      4.758      0.000       0.318       0.763
                                    Roots                                    
=============================================================================
                  Real          Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
MA.1           -1.8514           +0.0000j            1.8514            0.5000
-----------------------------------------------------------------------------
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=365.973, BIC=374.350, Fit time=0.091 seconds
Fit ARIMA: order=(0, 1, 0); AIC=381.727, BIC=385.916, Fit time=0.002 seconds
Fit ARIMA: order=(1, 1, 0); AIC=382.353, BIC=388.636, Fit time=0.014 seconds
Fit ARIMA: order=(0, 1, 1); AIC=372.254, BIC=378.537, Fit time=0.053 seconds
Fit ARIMA: order=(2, 1, 1); AIC=375.361, BIC=385.832, Fit time=0.061 seconds
Fit ARIMA: order=(1, 1, 2); AIC=362.365, BIC=372.837, Fit time=0.168 seconds
Fit ARIMA: order=(2, 1, 3); AIC=nan, BIC=nan, Fit time=nan seconds
Fit ARIMA: order=(0, 1, 2); AIC=360.686, BIC=369.063, Fit time=0.085 seconds
Fit ARIMA: order=(0, 1, 3); AIC=362.298, BIC=372.770, Fit time=0.109 seconds
Fit ARIMA: order=(1, 1, 3); AIC=nan, BIC=nan, Fit time=nan seconds
Total fit time: 0.609 seconds
                             ARIMA Model Results                              
==============================================================================
Dep. Variable:                    D.y   No. Observations:                   60
Model:                 ARIMA(0, 1, 2)   Log Likelihood                -176.343
Method:                       css-mle   S.D. of innovations              4.437
Date:                Mon, 02 Aug 2021   AIC                            360.686
Time:                        17:13:20   BIC                            369.063
Sample:                             1   HQIC                           363.962
                                                                              
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const         -0.0063      0.049     -0.128      0.899      -0.103       0.090
ma.L1.D.y     -0.4519      0.122     -3.696      0.000      -0.692      -0.212
ma.L2.D.y     -0.5480      0.115     -4.760      0.000      -0.774      -0.322
                                    Roots                                    
=============================================================================
                  Real          Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
MA.1            1.0000           +0.0000j            1.0000            0.0000
MA.2           -1.8246           +0.0000j            1.8246            0.5000
-----------------------------------------------------------------------------
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=425.526, BIC=429.682, Fit time=0.002 seconds
Fit ARIMA: order=(1, 2, 0); AIC=417.450, BIC=423.682, Fit time=0.016 seconds
Fit ARIMA: order=(0, 2, 1); AIC=382.451, BIC=388.683, Fit time=0.019 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.069 seconds
                             ARIMA Model Results                              
==============================================================================
Dep. Variable:                   D2.y   No. Observations:                   59
Model:                 ARIMA(0, 2, 1)   Log Likelihood                -188.225
Method:                       css-mle   S.D. of innovations              5.678
Date:                Mon, 02 Aug 2021   AIC                            382.451
Time:                        17:13:21   BIC                            388.683
Sample:                             2   HQIC                           384.884
                                                                              
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const         -0.0109      0.042     -0.258      0.797      -0.094       0.072
ma.L1.D2.y    -1.0000      0.043    -23.487      0.000      -1.083      -0.917
                                    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    7.782204
2021    7.409721
2022    7.409721
2023    7.409721
2024    7.409721
2025    7.409721
2026    7.409721
2027    7.409721
2028    7.409721
2029    7.409721
dtype: float64

2020   -0.844994
2021   -2.395531
2022   -2.395531
2023   -2.395531
2024   -2.395531
2025   -2.395531
2026   -2.395531
2027   -2.395531
2028   -2.395531
2029   -2.395531
dtype: float64

2020    16.409402
2021    17.214973
2022    17.214973
2023    17.214973
2024    17.214973
2025    17.214973
2026    17.214973
2027    17.214973
2028    17.214973
2029    17.214973
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  1960                                   1.779878
1  1961                                   1.695213
2  1962                                   3.632215
3  1963                                   2.946161
4  1964                                  13.355261

   Year  Inflation_ConsumerPrice_Annual_Percentage    End_Year
0  1960                                   1.779878  1960-12-31
1  1961                                   1.695213  1961-12-31
2  1962                                   3.632215  1962-12-31
3  1963                                   2.946161  1963-12-31
4  1964                                  13.355261  1964-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
56 2016-12-31  4.948216
57 2017-12-31  3.328173
58 2018-12-31  3.945069
59 2019-12-31  3.723276
60 2020-12-31  6.623437

           ds
45 2005-12-31
46 2006-12-31
47 2007-12-31
48 2008-12-31
49 2009-12-31
50 2010-12-31
51 2011-12-31
52 2012-12-31
53 2013-12-31
54 2014-12-31
55 2015-12-31
56 2016-12-31
57 2017-12-31
58 2018-12-31
59 2019-12-31
60 2020-12-31
61 2021-12-31
62 2022-12-31
63 2023-12-31
64 2024-12-31
65 2025-12-31
66 2026-12-31
67 2027-12-31
68 2028-12-31
69 2029-12-31
70 2030-12-31
           ds      yhat  yhat_lower  yhat_upper
46 2006-12-31  6.028682    0.088391   11.867177
47 2007-12-31  7.688201    1.756876   13.498522
48 2008-12-31  5.397628   -0.609384   10.934561
49 2009-12-31  9.483043    3.676600   14.991182
50 2010-12-31  4.884861   -0.859146   10.598144
51 2011-12-31  8.008366    2.063270   13.759623
52 2012-12-31  6.402636    0.412148   12.400100
53 2013-12-31  8.620527    3.073390   14.317107
54 2014-12-31  6.340415    0.380478   12.150023
55 2015-12-31  9.936317    4.468667   15.804751
56 2016-12-31  6.722801    1.231096   12.499673
57 2017-12-31  5.440893   -1.069311   11.483002
58 2018-12-31  7.345424    1.565443   13.181996
59 2019-12-31  9.073801    2.969273   15.024643
60 2020-12-31  8.650751    2.911456   14.885012
61 2021-12-31  4.297072   -1.313786   10.198395
62 2022-12-31  7.665589    1.655584   13.772217
63 2023-12-31  5.894167   -0.237867   11.666082
64 2024-12-31  7.788236    1.868627   13.530374
65 2025-12-31  5.752627   -0.174003   11.806225
66 2026-12-31  9.593539    3.596576   15.636521
67 2027-12-31  4.750346   -1.363836   10.725931
68 2028-12-31  4.608602   -1.126077   10.627635
69 2029-12-31  6.757635    0.818091   12.396389
70 2030-12-31  8.731024    2.570148   14.248326
         Year       yhat  yhat_lower  yhat_upper  \
0  1960-12-31   7.677374    1.602589   13.257600   
1  1961-12-31   6.395467    0.555957   11.777781   
2  1962-12-31   8.299998    2.189640   13.871748   
3  1963-12-31  10.028377    3.748771   16.133271   
4  1964-12-31   9.605326    3.820560   15.637101   
..        ...        ...         ...         ...   
66 2026-12-31   9.593539    3.596576   15.636521   
67 2027-12-31   4.750346   -1.363836   10.725931   
68 2028-12-31   4.608602   -1.126077   10.627635   
69 2029-12-31   6.757635    0.818091   12.396389   
70 2030-12-31   8.731024    2.570148   14.248326   

    Inflation_ConsumerPrice_Annual_Percentage  
0                                    1.779878  
1                                    1.695213  
2                                    3.632215  
3                                    2.946161  
4                                   13.355261  
..                                        ...  
66                                        NaN  
67                                        NaN  
68                                        NaN  
69                                        NaN  
70                                        NaN  

[71 rows x 5 columns]
In [ ]: