"""
# Problem Statement
A bike-sharing system is a service in which bikes are made available for shared use to individuals on a short term basis for a price or free. Many bike share systems allow people to borrow a bike from a "dock" which is usually computer-controlled wherein the user enters the payment information, and the system unlocks it. This bike can then be returned to another dock belonging to the same system.


A US bike-sharing provider BoomBikes has recently suffered considerable dips in their revenues due to the ongoing Corona pandemic. The company is finding it very difficult to sustain in the current market scenario. So, it has decided to come up with a mindful business plan to be able to accelerate its revenue as soon as the ongoing lockdown comes to an end, and the economy restores to a healthy state.

In such an attempt, BoomBikes aspires to understand the demand for shared bikes among the people after this ongoing quarantine situation ends across the nation due to Covid-19. They have planned this to prepare themselves to cater to the people's needs once the situation gets better all around and stand out from other service providers and make huge profits.


They have contracted a consulting company to understand the factors on which the demand for these shared bikes depends. Specifically, they want to understand the factors affecting the demand for these shared bikes in the American market. The company wants to know:
- Which variables are significant in predicting the demand for shared bikes.
- How well those variables describe the bike demands

Based on various meteorological surveys and people's styles, the service provider firm has gathered a large dataset on daily bike demands across the American market based on some factors. 

## Business Goal:
You are required to model the demand for shared bikes with the available independent variables. It will be used by the management to understand how exactly the demands vary with different features. They can accordingly manipulate the business strategy to meet the demand levels and meet the customer's expectations. Further, the model will be a good way for management to understand the demand dynamics of a new market. 
"""
### Import important libraries

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
### Read the file

bike=pd.read_csv("/kaggle/input/bikesharing/day.csv")
bike.head()
### Dataframe shape

bike.shape
###Information

bike.info()
"""
***There is no null value***
"""
### Change season into proper format  as these have some labels

bike['season']=bike['season'].replace({1:'spring', 2:'summer', 3:'fall', 4:'winter'})

### Change weathersit into proper format

bike['weathersit']=bike['weathersit'].replace({1:'Sunny/Partial cloudy', 2:'cloudy/Misty', 3:'Light rainy/Light snowy', 4:'Heavy rainy/heavy snowy'})

### Change weekday into proper format

bike['weekday']=bike['weekday'].replace({1:'Monday', 2:'Tuesday', 3:'Wednesday', 4:'Thrusday',5:'Friday',6:'Saturday',7:'Sunday'})
### Change weekday into proper format

bike['mnth']=bike['mnth'].replace({1:'Jan', 2:'Feb', 3:'Mar', 4:'Apr',5:'May',6:'Jun',7:'Jul',8:'Aug',9:'Sep',10:'Oct',11:'Nov',12:'Dec'})

###check dataframe again to check whether all above 4 codes are applied correctly or not

bike.head()
### Fetching list of all numerical values

bike.describe().columns.to_list()
### Outlier detection


plt.figure(figsize=[15,18])


bike_num=['instant',
 'yr',
 'holiday',
 'workingday',
 'temp',
 'atemp',
 'hum',
 'windspeed',
 'casual',
 'registered',
 'cnt']
c=1

for i in bike_num:
    plt.subplot(3, 4, c)
    plt.title('{}'.format(i))
    plt.xlabel(i)
    sns.boxplot(bike[i])
    c = c + 1
    
plt.show()
"""
**There is no outliers,we are good to go**
"""
"""
# Visualization
"""
###pairplot

sns.pairplot(bike)
plt.show()
"""
**We can observe that there are some linear relationship between target variable(cnt) and some independent variables**
"""
### We can drop thsese column because it has no significance

bike.drop(['dteday'],axis=1,inplace=True)
bike.drop(['instant'],axis=1,inplace=True)
bike.drop(['casual'],axis=1,inplace=True)
bike.drop(['registered'],axis=1,inplace=True)

###Checkinga dataframe again
bike.head()
###Correlation using heatmap

plt.figure(figsize=[11,7])
bike_corr=bike[['yr','holiday','workingday','temp','atemp','hum','windspeed','cnt']].corr()
sns.heatmap(data=bike_corr,annot=True)
plt.show()
"""
- Target variable is highly correlated with registered
- Target variable is moderately correlated with temp,atemp,year and casual

"""
### We can drop either atemp or temp because of high correlation
### Dropping atemp
bike.drop(['temp'],axis=1,inplace=True)
"""
### Looking pattern into categorical columns


"""
### Looking pattern into categorical columns using boxplots

plt.figure(figsize=(20, 12))

plt.subplot(2,2,1)
sns.boxplot(x = 'season', y = 'cnt', data = bike)

plt.subplot(2,2,2)
sns.boxplot(x = 'mnth', y = 'cnt', data = bike)

plt.subplot(2,2,3)
sns.boxplot(x = 'weekday', y = 'cnt', data = bike)

plt.subplot(2,2,4)
sns.boxplot(x = 'weathersit', y = 'cnt', data = bike)

plt.show()
"""
- In spring season deamnd is less.
- In the month of January and December demands are lowest while highest in the month.
- In light rainy/light snowny demand is lowest while in sunny demand is highest
"""
"""
# Data Prepartion
"""
### Dummy variable

### Season,mnth,weekdays and weathersit have some lebels
### Change these labels into 0/1.
### We are dropping first column because to minimize redundancy.
season_d=pd.get_dummies(bike['season'],drop_first = True)
mnth_d=pd.get_dummies(bike['mnth'],drop_first = True)
weekday_d=pd.get_dummies(bike['weekday'],drop_first = True)
weathersit_d=pd.get_dummies(bike['weathersit'],drop_first = True)
### Add the above results into original data set

bike=pd.concat([bike,season_d,mnth_d,weekday_d,weathersit_d],axis=1)
bike.head()
## Checking columns
bike.columns
### Drop Season,mnth,weekday,weathersit columns because these are no more significant.

bike=bike.drop(['season','mnth','weekday','weathersit'],axis=1)
bike.head()
"""
## Spliting data set into train and test
"""
from sklearn.model_selection import train_test_split
np.random.seed(0)
bike_train, bike_test = train_test_split(bike, train_size = 0.7, random_state = 100)
### checking shape of splitted data frame
print(bike_train.shape)
print(bike_test.shape)
"""
## Rescaling using MinMaxScaler
"""
bike_train.head()
### Importing MinMaxScaler
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()



###Variable on which scaling to be applied are,
bike_num=['atemp','hum','windspeed','cnt']

### Apply Scaler

bike_train[bike_num] = scaler.fit_transform(bike_train[bike_num])
bike_train.describe()
"""
**Scaling applied successfully**
"""
### Regplot for target variable with independent variable for train data set to check linear relationship.

plt.figure(figsize=[20,7])

plt.subplot(1,3,1)
sns.regplot(data=bike_train,x='atemp',y='cnt')


plt.subplot(1,3,2)
sns.regplot(data=bike_train,x='hum',y='cnt')

plt.subplot(1,3,3)
sns.regplot(data=bike_train,x='windspeed',y='cnt')


plt.show()
"""
**We can clearly see that target variable has many linear relationship with independent variables**
"""
### Separate target and independent variables

y_train = bike_train.pop('cnt')
X_train = bike_train
### Checking shape of target and independent dataframe
print(y_train.shape)
print(X_train.shape)
### Using RFE,we will find top 10 columns

#Importing libraries
from sklearn.feature_selection import RFE
from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(X_train, y_train)

rfe = RFE(model, 10)            
rfe = rfe.fit(X_train, y_train)
list(zip(X_train.columns,rfe.support_,rfe.ranking_))
### Top 10 columns
top_10_col = X_train.columns[rfe.support_]
top_10_col
### selecting top 10 independent variable,selected using RFE method
X_train_top_10 = X_train[top_10_col]
X_train_top_10.shape
import statsmodels.api as sm 
# Adding a constant variable to avoid line passing through origin
 
X_train_cons = sm.add_constant(X_train_top_10)
# Creating first model 
mlr = sm.OLS(y_train, X_train_cons).fit()
### Fetching constant and coefficients of models
mlr.params
### Fetching summaries like p-value,r-squared,adjusted r-squared etc. of model

print(mlr.summary())
"""
- Before dropping columns we will also ckeck VIF of independent variables
- VIF is used to check multicollinearity between independent variables
"""
### Importing libraries to check VIF

from statsmodels.stats.outliers_influence import variance_inflation_factor
### Checking VIF value i.e multicollinearity

vif = pd.DataFrame()
vif['Features'] = X_train_top_10.columns
vif['VIF'] = [variance_inflation_factor(X_train_top_10.values, i) for i in range(X_train_top_10.shape[1])]
vif['VIF'] = round(vif['VIF'], 2)
vif = vif.sort_values(by = "VIF", ascending = False)
vif
### First we will drop which are highly insignificant and hight VIF i.e
### Dropping hum because of high VIF value

X_dropped = X_train_top_10.drop('hum', 1)
X_dropped.shape
# Building second model
X_train_cons = sm.add_constant(X_dropped)

mlr2 = sm.OLS(y_train, X_train_cons).fit()
### summaries of second model

print(mlr2.summary())
### Checking VIFs for second model

vif = pd.DataFrame()
vif['Features'] = X_dropped.columns
vif['VIF'] = [variance_inflation_factor(X_dropped.values, i) for i in range(X_dropped.shape[1])]
vif['VIF'] = round(vif['VIF'], 2)
vif = vif.sort_values(by = "VIF", ascending = False)
vif
### Next,We will drop 'Sunny/Partial cloudy' because it has high VIF value'
X_dropped = X_dropped.drop('Sunny/Partial cloudy', 1,)
X_dropped.shape
# Building third  model
X_train_cons = sm.add_constant(X_dropped)

mlr3 = sm.OLS(y_train, X_train_cons).fit()

### Summaries of third model

print(mlr3.summary())
### Checking VIFs for third model

vif = pd.DataFrame()
vif['Features'] = X_dropped.columns
vif['VIF'] = [variance_inflation_factor(X_dropped.values, i) for i in range(X_dropped.shape[1])]
vif['VIF'] = round(vif['VIF'], 2)
vif = vif.sort_values(by = "VIF", ascending = False)
vif
X_train_cons.head()
X_train_cons.columns
X_train_latest = X_train_cons.drop(['const'], axis=1)
X_train_latest.columns
"""
# mlr3 is the decent  model
"""
### Residual analysis

y_train_pred = mlr3.predict(X_train_cons)
# plotting distribution plot to check distribution of error terms

plt.figure(figsize=[8,5])
error = y_train - y_train_pred
sns.distplot(error, hist=False,bins = 50)
plt.title('Distribution of residual term')                
plt.show()    
"""
**Errors are normally distributed with mean is equal to zero**
"""
"""
### Making prediction using mlr3



"""
###Variable on which scaling to be applied are,
bike_num=['atemp','hum','windspeed','cnt']

### Apply Scaler

bike_test[bike_num] = scaler.transform(bike_test[bike_num])
bike_test.describe()
### Splitting test data set into dependent and independent variable
y_test = bike_test.pop('cnt')
X_test = bike_test
# Now let's use our model to make predictions.

# Creating X_test_cons with columns using final X_tain
X_test_cons = X_test[X_train_latest.columns]

# Adding a constant variable to avoid line passing through origin
X_test_cons = sm.add_constant(X_test_cons)
# Making predictions using final model i.e mlr3
y_pred = mlr3.predict(X_test_cons)
### Importing library to compare r-squared

from sklearn.metrics import r2_score

### R-squared for test dataframe
print(r2_score(y_test, y_pred))

### R-squared for train dataframe
print(r2_score(y_train, y_train_pred))
"""
### Tthe R-squared for train and test both dataframe within acceptable range
- R-Squared_test:76.8
- R-Squared_train :78.1
"""
"""
# Equation of Final model is

<span style='color:green'> **Demand= 0.1175 + 0.2394(yr)-0.0823(holiday) + 0.5795(atemp) - 0.1628(windspeed) + 0.0821(summer) + 0.1070(winter) + 0.0919(sep) - 0.0658(cloud/misty)**
"""