<jupyter_start><jupyter_text>Furniture Sales Time Series Model<jupyter_code>import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
#loading the data
df= pd.read_excel('Furniture-Sales.xls',sheet_name='Orders',index_col='Row ID')
df.shape
df.columns
df.head()
df.dtypes<jupyter_output><empty_output><jupyter_text>Data Preprocessing<jupyter_code># Taking the order date and sales in our data as we only need that to predict future sales as per time series model.
data= df.drop(['Order ID','Ship Date', 'Ship Mode', 'Customer ID',
       'Customer Name', 'Segment', 'Country', 'City', 'State', 'Postal Code',
       'Region', 'Product ID', 'Category', 'Sub-Category', 'Product Name',
        'Quantity', 'Discount', 'Profit'], axis=1)
data.head()
# Now as we see in data we have more than one sales for a particular date
# so we will group the data by date and will do the sum of its sales
data = data.groupby('Order Date', sort=True)['Sales'].sum().reset_index()
data.set_index('Order Date', inplace=True)
# So if you want you can slice it now with day, date or year
data['2014-01']<jupyter_output><empty_output><jupyter_text>Now as we know mainly sales are done with Monthly prediction so we will change the freq of daily to monthly with avg monthly sales and will take first of every month.<jupyter_code>data = data.resample('MS').mean()
data['2017']<jupyter_output><empty_output><jupyter_text>Seasonality Check<jupyter_code># Visulaizing the data
data.plot(figsize=(15,5))
plt.show()<jupyter_output><empty_output><jupyter_text>Now if we will see in graph, Per year sales is less in starting month and max in end month with low sales in few mid month. Which represent the seasonality trend both<jupyter_code># We have seasonal decompose class whcih returns all the following plot data
from statsmodels.tsa.seasonal import seasonal_decompose
decom= seasonal_decompose(data, model= 'additive')
# Seasonal
decom.seasonal.plot(figsize= (15,5))
# Trend
decom.trend.plot(figsize= (15,5))<jupyter_output><empty_output><jupyter_text>We can see we have very less increasing trend in our data, starting from july 2015<jupyter_code>#Residuals
decom.resid.plot(figsize=(15,5))
#original data plot
decom.observed.plot(figsize=(15,5))
# Now as we have Trend we will try to use lag to check trend.
diff= data.diff(periods=1)
seasonal_decompose(diff.dropna(),model='additive').trend.plot(figsize=(15,5))<jupyter_output><empty_output><jupyter_text>Now we can see with One lag , we can see increasing trend is gone, which we can use for model.<jupyter_code>from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plot_acf(data)<jupyter_output><empty_output><jupyter_text>Acf plot also suggest with no linear trend<jupyter_code># now getting training and testing data set 
train= data.iloc[0:36,:]
test= data.iloc[36:48,:]
print(train.shape, test.shape)
import warnings
warnings.filterwarnings('ignore')
import itertools as it
p=d=q=range(0,2)
pdq= list(it.product(p,d,q))
seasonal_pdq=[(x[0], x[1], x[2], 12) for x in list(it.product(p, d, q))]
print('Examples of parameter combinations for Seasonal ARIMA...')
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[1]))
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[2]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[3]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[4]))
from statsmodels.tsa.api import SARIMAX
pair= {}
for param in pdq:
    for param_seasonal in seasonal_pdq:
        try:
            mod = SARIMAX(data,order=param,
                            seasonal_order=param_seasonal,
                            enforce_stationarity=False,
                            enforce_invertibility=False)
            results = mod.fit()
            pair[results.aic]=(param,param_seasonal)
#             print('ARIMA{}x{}12 - AIC:{}'.format(param, param_seasonal, results.aic))
        except:
            continue
best_order,best_s_order= pair[min(pair.keys())]
print(best_order,best_s_order)
final_model= SARIMAX(data,order=best_order,seasonal_order=best_s_order).fit()
final_model.summary()
final_model.plot_diagnostics(figsize=(16, 8))
plt.show()<jupyter_output><empty_output><jupyter_text>our model diagnostics suggests that the model residuals are near normally distributed.<jupyter_code>yp= final_model.predict(start='2017-01-01', end='2017-12-01')
plt.figure(figsize=(15,5))
plt.plot(train,'blue',label='Train')
plt.plot(test,'red',label='Test')
plt.plot(yp,'green',label='Pred')
plt.legend(loc='best')
plt.show()
from sklearn.metrics import mean_squared_error, r2_score

print('rmse:{}'.format(np.sqrt(mean_squared_error(test,yp))))
print('R2 Score:{}'.format(r2_score(test,yp)))
plt.figure(figsize=(15,5))
plt.plot(data,'blue',label='Train')
plt.plot(final_model.forecast(steps=100),'green')
plt.show()<jupyter_output><empty_output><jupyter_text>So now with R2 of .65 and above we cn consider it as a good model. Which captured trend and seasonality both for future also.<jupyter_code>from pmdarima.arima import auto_arima
final_model= auto_arima(data, start_p=0, start_q=0,d=1,
                           max_p=3,max_q=3, m=12,
                           start_P=0,D=1,start_Q=0 ,seasonal=True,
                           max_P=3,max_Q=3, trace=True,
                           error_action='ignore',  
                           suppress_warnings=True, 
                           stepwise=True)
model= final_model.fit(data)
forecast = model.predict(n_periods=len(test))
forecast = pd.DataFrame(forecast,index = test.index, columns=['Prediction'])
print('rmse:{}'.format(np.sqrt(mean_squared_error(test['Sales'],forecast['Prediction']))))
print('R2 Score:{}'.format(r2_score(test['Sales'],forecast['Prediction'])))
plt.figure(figsize=(15,5))
plt.plot(train['Sales'],'blue',label='Train')
plt.plot(test['Sales'],'red',label='Test')
plt.plot(forecast['Prediction'],'green',label='Pred')
plt.legend(loc='best')
plt.show()<jupyter_output>rmse:662.4781334247258
R2 Score:0.3179815659687161
StarcoderdataJupyterStructuredCleanDedup