# Setup feedback system
from learntools.core import binder
binder.bind(globals())
from learntools.time_series.ex1 import *

# Setup notebook
from pathlib import Path
from learntools.time_series.style import *  # plot style settings

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from sklearn.linear_model import LinearRegression


data_dir = Path('../input/ts-course-data/')
comp_dir = Path('../input/store-sales-time-series-forecasting')

book_sales = pd.read_csv(
    data_dir / 'book_sales.csv',
    index_col='Date',
    parse_dates=['Date'],
).drop('Paperback', axis=1)
book_sales['Time'] = np.arange(len(book_sales.index))
book_sales['Lag_1'] = book_sales['Hardcover'].shift(1)
book_sales = book_sales.reindex(columns=['Hardcover', 'Time', 'Lag_1'])

ar = pd.read_csv(data_dir / 'ar.csv')

dtype = {
    'store_nbr': 'category',
    'family': 'category',
    'sales': 'float32',
    'onpromotion': 'uint64',
}
store_sales = pd.read_csv(
    comp_dir / 'train.csv',
    dtype=dtype,
    parse_dates=['date'],
    infer_datetime_format=True,
)
store_sales = store_sales.set_index('date').to_period('D')
store_sales = store_sales.set_index(['store_nbr', 'family'], append=True)
average_sales = store_sales.groupby('date').mean()['sales']

"""
Explanation: Introduction
Run this cell to set everything up!
End of explanation
"""


fig, ax = plt.subplots()
ax.plot('Time', 'Hardcover', data=book_sales, color='0.75')
ax = sns.regplot(x='Time', y='Hardcover', data=book_sales, ci=None, scatter_kws=dict(color='0.25'))
ax.set_title('Time Plot of Hardcover Sales');

"""
Explanation: One advantage linear regression has over more complicated algorithms is that the models it creates are explainable -- it's easy to interpret what contribution each feature makes to the predictions. In the model target = weight * feature + bias, the weight tells you by how much the target changes on average for each unit of change in the feature.
Run the next cell to see a linear regression on Hardcover Sales.
End of explanation
"""


# View the solution (Run this line to receive credit!)
q_1.check()

# Uncomment the next line for a hint
#_COMMENT_IF(PROD)_
q_1.hint()

"""
Explanation: 1) Interpret linear regression with the time dummy
The linear regression line has an equation of (approximately) Hardcover = 3.33 * Time + 150.5. Over 6 days how much on average would you expect hardcover sales to change? After you've thought about it, run the next cell.
End of explanation
"""


fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(11, 5.5), sharex=True)
ax1.plot(ar['ar1'])
ax1.set_title('Series 1')
ax2.plot(ar['ar2'])
ax2.set_title('Series 2');

"""
Explanation: Interpreting the regression coefficients can help us recognize serial dependence in a time plot. Consider the model target = weight * lag_1 + error, where error is random noise and weight is a number between -1 and 1. The weight in this case tells you how likely the next time step will have the same sign as the previous time step: a weight close to 1 means target will likely have the same sign as the previous step, while a weight close to -1 means target will likely have the opposite sign.
2) Interpret linear regression with a lag feature
Run the following cell to see two series generated according to the model just described.
End of explanation
"""


# View the solution (Run this cell to receive credit!)
q_2.check()

# Uncomment the next line for a hint
#_COMMENT_IF(PROD)_
q_2.hint()

"""
Explanation: One of these series has the equation target = 0.95 * lag_1 + error and the other has the equation target = -0.95 * lag_1 + error, differing only by the sign on the lag feature. Can you tell which equation goes with each series?
End of explanation
"""


from sklearn.linear_model import LinearRegression

df = average_sales.to_frame()

# YOUR CODE HERE: Create a time dummy
time = ____

#_UNCOMMENT_IF(PROD)_
#df['time'] = time 

# YOUR CODE HERE: Create training data
X = ____  # features
y = ____  # target

# Train the model
#_UNCOMMENT_IF(PROD)_
#model = LinearRegression()
#_UNCOMMENT_IF(PROD)_
#model.fit(X, y)

# Store the fitted values as a time series with the same time index as
# the training data
#_UNCOMMENT_IF(PROD)_
#y_pred = pd.Series(model.predict(X), index=X.index)


# Check your answer
q_3.check()

# Lines below will give you a hint or solution code
#_COMMENT_IF(PROD)_
q_3.hint()
#_COMMENT_IF(PROD)_
q_3.solution()

#%%RM_IF(PROD)%%
from sklearn.linear_model import LinearRegression

df = average_sales.to_frame()

time = np.ones_like(df.index)

df['time'] = time

X = df.loc[:, ['time']]
y = df.loc[:, 'sales']

model = LinearRegression()
model.fit(X, y)

y_pred = pd.Series(model.predict(X), index=X.index)

q_3.assert_check_failed()

#%%RM_IF(PROD)%%
from sklearn.linear_model import LinearRegression

df = average_sales.to_frame()

time = np.arange(len(df.index))

df['time'] = time

X = df.loc[:, ['sales']]
y = df.loc[:, 'time']

model = LinearRegression()
model.fit(X, y)

y_pred = pd.Series(model.predict(X), index=X.index)

q_3.assert_check_failed()

#%%RM_IF(PROD)%%
from sklearn.linear_model import LinearRegression

df = average_sales.to_frame()

time = np.arange(len(df.index))

df['time'] = time

X = df.loc[:, ['time']]
y = df.loc[:, 'sales']

model = LinearRegression()
model.fit(X, y)

y_pred = pd.Series(model.predict(X), index=X.index)

q_3.assert_check_passed()

"""
Explanation: Now we'll get started with the Store Sales - Time Series Forecasting competition data. The entire dataset comprises almost 1800 series recording store sales across a variety of product families from 2013 into 2017. For this lesson, we'll just work with a single series (average_sales) of the average sales each day.
3) Fit a time-step feature
Complete the code below to create a linear regression model with a time-step feature on the series of average product sales. The target is in a column called 'sales'.
End of explanation
"""


ax = y.plot(**plot_params, alpha=0.5)
ax = y_pred.plot(ax=ax, linewidth=3)
ax.set_title('Time Plot of Total Store Sales');

"""
Explanation: Run this cell if you'd like to see a plot of the result.
End of explanation
"""


df = average_sales.to_frame()

# YOUR CODE HERE: Create a lag feature from the target 'sales'
lag_1 = ____

#_UNCOMMENT_IF(PROD)_
#df['lag_1'] = lag_1  # add to dataframe

#_UNCOMMENT_IF(PROD)_
#X = df.loc[:, ['lag_1']].dropna()  # features
#_UNCOMMENT_IF(PROD)_
#y = df.loc[:, 'sales']  # target
#_UNCOMMENT_IF(PROD)_
#y, X = y.align(X, join='inner')  # drop corresponding values in target

# YOUR CODE HERE: Create a LinearRegression instance and fit it to X and y.
model = ____

# YOUR CODE HERE: Create Store the fitted values as a time series with
# the same time index as the training data
y_pred = ____


# Check your answer
q_4.check()

# Lines below will give you a hint or solution code
q_4.hint()
q_4.solution()

#%%RM_IF(PROD)%%
df = average_sales.to_frame()

lag_1 = df['sales']

df['lag_1'] = lag_1

X = df.loc[:, ['lag_1']]
X.dropna(inplace=True)  # drop missing values in the feature set
y = df.loc[:, 'sales']  # create the target
y, X = y.align(X, join='inner')  # drop corresponding values in target

model = LinearRegression()
model.fit(X, y)

y_pred = pd.Series(model.predict(X), index=X.index)

q_4.assert_check_failed()

#%%RM_IF(PROD)%%
df = average_sales.to_frame()

lag_1 = df['sales'].shift(-1)

df['lag_1'] = lag_1

X = df.loc[:, ['lag_1']]
X.dropna(inplace=True)  # drop missing values in the feature set
y = df.loc[:, 'sales']  # create the target
y, X = y.align(X, join='inner')  # drop corresponding values in target

model = LinearRegression()
model.fit(X, y)

y_pred = pd.Series(model.predict(X), index=X.index)

q_4.assert_check_failed()

#%%RM_IF(PROD)%%
df = average_sales.to_frame()

lag_1 = df['sales'].shift(1)

df['lag_1'] = lag_1

X = df.loc[:, ['sales']]
X.dropna(inplace=True)  # drop missing values in the feature set
y = df.loc[:, 'lag_1']  # create the target
y.dropna(inplace=True)
y, X = y.align(X, join='inner')  # drop corresponding values in target

model = LinearRegression()
model.fit(X, y)

y_pred = pd.Series(model.predict(X), index=X.index)

q_4.assert_check_failed()

#%%RM_IF(PROD)%%
df = average_sales.to_frame()

lag_1 = df['sales'].shift(1)

df['lag_1'] = lag_1

X = df.loc[:, ['lag_1']]
X.dropna(inplace=True)  # drop missing values in the feature set
y = df.loc[:, 'sales']  # create the target
y, X = y.align(X, join='inner')  # drop corresponding values in target

model = LinearRegression()
model.fit(X, y)

y_pred = pd.Series(model.predict(X), index=X.index)

q_4.assert_check_passed()

"""
Explanation: 4) Fit a lag feature to Store Sales
Complete the code below to create a linear regression model with a lag feature on the series of average product sales. The target is in a column of df called 'sales'.
End of explanation
"""


fig, ax = plt.subplots()
ax.plot(X['lag_1'], y, '.', color='0.25')
ax.plot(X['lag_1'], y_pred)
ax.set(aspect='equal', ylabel='sales', xlabel='lag_1', title='Lag Plot of Average Sales');

"""
Explanation: Run the next cell if you'd like to see the result.
End of explanation
"""


