<jupyter_start><jupyter_text>ARIMA ARIMA adalah metode statistikal yang cukup populer digunakan untuk time series forecasting dan data analysis. ARIMA adalah singkatan dari AutoRegressive Integrated Moving Average. Metode ini menangkap struktur dari sebuah time series data untuk mengetahui pola dari data tersebut.ARIMA mempunyai 2 jenis, yaitu:1. Non-seasonal ARIMA2. Seasonal ARIMAARIMA model biasanya digunakan dalam kasus dimana data terplot secara non-stationary, dimana akan diberlakukan langkah differencing pada data yang diobservasi sehingga data terplot menjadi stationary.Non-seasonal ARIMA secara umum mempunyai 3 parameter, yaitu p, d, dan q. parameter-parameter ini bernilai non-negative.1. AR(p):AutoRegression. Regresi yang memanfaatkan fitur-fitur antara parameter yang diamati terhadap parameter sebelumnya.2. I(d):Integrated. Dilakukan Operasi selisih antara data point yang diamati terhadap data point pada waktu sebelumnya (t-1). Hal ini dilakukan untuk membuat time series menjadi stationary.3. MA(q):Moving Average. Nilai yang mempunyai ketergantungan terhadap parameter yang diamati dan error pada model Moving Average.Untuk memaksimalkan model ARIMA, kita harus membuat data terplot secara stationary. Data time-series stationary adalah data yang mempunyai nilai rata-rata dan varian yang konstan terhadap waktu. Stationary data dibutuhkan agar model bisa membuat prediksi dengan baik. Berikut adalah contoh data stationary dan non-stationary. ![image.png](attachment:image.png) Jika data yang kita peroleh bersifat non-stationary, maka kita harus mengubah data tersebut menjadi stationary agar kita bisa mengevaluasi dan menentukan parameter-parameter pada ARIMA. Caranya adalah melakukan differencing. ![image.png](attachment:image.png) Cara kerjanya relatif mudah dimengerti. jadi saat data bersifat non-stationary saat kita amati, maka kita bisa melakukan differencing tahap pertama. Jika saat differencing pertama telah dilakukan namun data masih bersifat non-stationary saat kita amati, maka kita bisa melakukan differencing tahap kedua. Differencing bisa terus dilakukan sampai data yang kita peroleh bersifat stationary. Yang harus kita perhatikan diatas adalah setiap melakukan differencing, maka kita akan mengorbankan 1 baris data. Kita bisa melakukan differencing berdasarkan season/musim. Contoh, jika kita mempunyai data bulanan, kita bisa melakukan differencing dengan nilai 12, jika kita ingin mendefinisikan 1 musim = 1 tahun. Saat data kita menjadi stationary, maka kita mampu melanjutkan ke tahap selanjutnya, yaitu menentukan p, d, dan q. Sebelum menentukan nilai p, d, dan q, kita harus mengetahui AutoCorrelation Plots  AutoCorrelation plot menunjukan korelasi antara time series data terhadap data sebelumnya yang dimundurkan(lagged) sebesar x. Jadi y axis adalah nilai korelasi, x adalah jumlah unit waktu yang dimundurkan.Contoh jika kita mempunyai time series sebesar T, kita copy  menjadi 2. Kita hapus data pertama dari copy pertama, kemudian kita hapus data terakhir dari copy kedua. Dengan ini kita mempunyai data untuk membuat AutoCorrelation plot dengan lag unit sebesar 1. Gradual Decline![image.png](attachment:image.png) Sharp Drop-off![image.png](attachment:image.png) Bagaimana cara kita menentukan model mana yang harus kita pilih? apakah AR atau MA? Berapa nilai lag yang harus kita pilih? Saat AutoCorrelation Plot bernilai positif saat lag pertama(x=1), maka kita disarankan untuk menggunakan AR model. Sebaliknya, Saat AutoCorrelation Plot bernilai negatif saat lag pertama, maka kita disarankan untuk menggunakan MA model. Cara ini cukup baik untuk menentukan nilai p, d, dan q pada model ARIMA.p: jumlah lagd: jumlah tahap differencingq: Nilai ukuran terhadap Moving Average.Untuk Seasonal ARIMA, akan ada parameter tambahan yang akan kita gunakan.  CODING SECTION Proses ARIMA pada umumnya seperti berikut.1. Melakukan visualisasi time series data2. membuat data time series menjadi stationary.3. Plot AutoCorrelation 4. Menentukan parameter model ARIMA.5. menggunakan model untuk membuat prediksi.<jupyter_code>import numpy as np
import pandas as pd
import statsmodels.api as sm

import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings("ignore")
df = pd.read_csv('monthly-milk-production-pounds-p.csv')
df.head()
df.tail()
df.columns = ['Month','Milk in pounds per cow']
df.head()

df.drop(168,axis=0,inplace=True)
df['Month'] = pd.to_datetime(df['Month'])
df.head()
df.set_index('Month',inplace=True)
df.head()
df.describe()<jupyter_output><empty_output><jupyter_text>Visualisasi<jupyter_code>df.plot()
timeseries = df['Milk in pounds per cow']
timeseries.rolling(12).mean().plot(label='12 Month Rolling Mean')
timeseries.rolling(12).std().plot(label='12 Month Rolling Std')
timeseries.plot()
plt.legend()
timeseries.rolling(12).mean().plot(label='12 Month Rolling Mean')
timeseries.plot()
plt.legend()<jupyter_output><empty_output><jupyter_text>Decomposition<jupyter_code>from statsmodels.tsa.seasonal import seasonal_decompose
decomposition = seasonal_decompose(df['Milk in pounds per cow'], freq=12)  
fig = plt.figure()  
fig = decomposition.plot()  
fig.set_size_inches(15, 8)<jupyter_output><empty_output><jupyter_text>Stationary Test<jupyter_code>df.head()
from statsmodels.tsa.stattools import adfuller
result = adfuller(df['Milk in pounds per cow'])
print('Augmented Dickey-Fuller Test:')
labels = ['ADF Test Statistic','p-value','#Lags Used','Number of Observations Used']

for value,label in zip(result,labels):
    print(label+' : '+str(value) )
    
if result[1] <= 0.05:
    print("strong evidence against the null hypothesis, reject the null hypothesis. Data has no unit root and is stationary")
else:
    print("weak evidence against null hypothesis, time series has a unit root, indicating it is non-stationary ")
# Store in a function for later use!
def adf_check(time_series):
    """
    Pass in a time series, returns ADF report
    """
    result = adfuller(time_series)
    print('Augmented Dickey-Fuller Test:')
    labels = ['ADF Test Statistic','p-value','#Lags Used','Number of Observations Used']

    for value,label in zip(result,labels):
        print(label+' : '+str(value) )
    
    if result[1] <= 0.05:
        print("strong evidence against the null hypothesis, reject the null hypothesis. Data has no unit root and is stationary")
    else:
        print("weak evidence against null hypothesis, time series has a unit root, indicating it is non-stationary ")<jupyter_output><empty_output><jupyter_text>Differencing<jupyter_code>df['Milk First Difference'] = df['Milk in pounds per cow'] - df['Milk in pounds per cow'].shift(1)
adf_check(df['Milk First Difference'].dropna())
df['Milk First Difference'].plot()<jupyter_output><empty_output><jupyter_text>** Second Difference **<jupyter_code># Sometimes it would be necessary to do a second difference 
# This is just for show, we didn't need to do a second difference in our case
df['Milk Second Difference'] = df['Milk First Difference'] - df['Milk First Difference'].shift(1)
adf_check(df['Milk Second Difference'].dropna())
df['Milk Second Difference'].plot()<jupyter_output><empty_output><jupyter_text>** Seasonal Difference **<jupyter_code>df['Seasonal Difference'] = df['Milk in pounds per cow'] - df['Milk in pounds per cow'].shift(12)
df['Seasonal Difference'].plot()
# Seasonal Difference by itself was not enough!
adf_check(df['Seasonal Difference'].dropna())<jupyter_output>Augmented Dickey-Fuller Test:
ADF Test Statistic : -2.3354193143593993
p-value : 0.16079880527711304
#Lags Used : 12
Number of Observations Used : 143
weak evidence against null hypothesis, time series has a unit root, indicating it is non-stationary<jupyter_text>** Seasonal First Difference **<jupyter_code># You can also do seasonal first difference
df['Seasonal First Difference'] = df['Milk First Difference'] - df['Milk First Difference'].shift(12)
df['Seasonal First Difference'].plot()
adf_check(df['Seasonal First Difference'].dropna())
from statsmodels.graphics.tsaplots import plot_acf,plot_pacf
fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(211)
fig = sm.graphics.tsa.plot_acf(df['Seasonal First Difference'].iloc[13:], lags=40, ax=ax1)<jupyter_output><empty_output><jupyter_text>Modelling with ARIMA<jupyter_code># For non-seasonal data
from statsmodels.tsa.arima_model import ARIMA
# I recommend you glance over this!

# 
help(ARIMA)<jupyter_output>Help on class ARIMA in module statsmodels.tsa.arima_model:

class ARIMA(ARMA)
 |  ARIMA(endog, order, exog=None, dates=None, freq=None, missing='none')
 |  
 |  Autoregressive Integrated Moving Average ARIMA(p,d,q) Model
 |  
 |  Parameters
 |  ----------
 |  endog : array-like
 |      The endogenous variable.
 |  order : iterable
 |      The (p,d,q) order of the model for the number of AR parameters,
 |      differences, and MA parameters to use.
 |  exog : array-like, optional
 |      An optional array of exogenous variables. This should *not* include a
 |      constant or trend. You can specify this in the `fit` method.
 |  dates : array-like of datetime, optional
 |      An array-like object of datetime objects. If a pandas object is given
 |      for endog or exog, it is assumed to have a DateIndex.
 |  freq : str, optional
 |      The frequency of the time-series. A Pandas offset or 'B', 'D', 'W',
 |      'M', 'A', or 'Q'. This is optional if dates are given.
 |  
 |  
 |  Notes
[...]<jupyter_text>p: jumlah lagd: jumlah tahap differencingq: Nilai ukuran terhadap Moving Average.<jupyter_code># We have seasonal data!
model = sm.tsa.statespace.SARIMAX(df['Milk in pounds per cow'],order=(0,1,0), seasonal_order=(1,1,1,12))
results = model.fit()

results.resid.plot()
results.resid.plot(kind='kde')<jupyter_output><empty_output><jupyter_text>Prediction of Future Values<jupyter_code>df['forecast'] = results.predict(start = 150, end= 168, dynamic= True)  
df[['Milk in pounds per cow','forecast']].plot(figsize=(12,8))<jupyter_output><empty_output><jupyter_text>ForecastingThis requires more time periods, so let's create them with pandas onto our original dataframe!<jupyter_code>df.tail()
from pandas.tseries.offsets import DateOffset
future_dates = [df.index[-1] + DateOffset(months=x) for x in range(0,24) ]
future_dates
future_dates_df = pd.DataFrame(index=future_dates[1:],columns=df.columns)
future_df = pd.concat([df,future_dates_df])
future_df.head()

future_df.tail()
future_df['forecast'] = results.predict(start = 168, end = 188, dynamic= True)  
future_df[['Milk in pounds per cow', 'forecast']].plot(figsize=(12, 8))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09424379232505643, 'fraction_numerical': 0.013073739653875094, 'mean_word_length': 5.600248292985723, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '512969', 'license': 'MIT', 'n_tokens_mistral': 3731, 'n_tokens_neox': 3538, 'n_words': 1126, 'path': '2 Regression/2.4 ARIMA/ARIMA.ipynb', 'repo_name': 'jordihasianta/DS_Kitchen', 'size': '10632'}