# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the read-only "../input/" directory
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))

# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All" 
# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session
from sklearn import metrics
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

column_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
Boston_house_price=pd.read_csv("../input/boston-house-prices/housing.csv", header=None, delimiter=r"\s+", names=column_names)
price_df=pd.DataFrame(Boston_house_price)
price_df.head()
price_df.describe()
price_df.info()
"""
# Univariate Analysis
"""
"""
Checking the distribution of most variables:
"""
# let's plot all the columns to look at their distributions
for i in price_df.columns:
    plt.figure(figsize=(7, 4))
    sns.histplot(data=price_df, x=i, kde = True)
    plt.show()
corr=price_df.corr()
corr.shape
# Plotting the heatmap of correlation between features
plt.figure(figsize=(20,20))
sns.heatmap(corr, cbar=True, square= True, fmt='.1f', annot=True, annot_kws={'size':15}, cmap='Greens')
"""
There is a high positive corrilation between the following colums
1. The number of rooms and price of the house
2. The age of the house and the nitric oxide concentration
3. the proportion of non-ratian business that are present and the nitric oxide concentration.
4. Non-ratail business in the town have less amiunt of tax charged on the house.

The high negative corrilation is between the following columns
1. Non-retail business and distance from the employment centers.
2. Similarly, the nitric oxide concentration and distance from the employement centers.
3. Age of the house and the distance from the employment center.


"""
#Slitting the data
X=price_df.drop(['MEDV'], axis=1)
Y=price_df['MEDV']

from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test=train_test_split(X,Y, test_size=0.3, random_state=4)
"""
# Linear Regression
"""
"""
Training the model
"""
#import the library for Linear Regression
from sklearn.linear_model import LinearRegression

# Create a linear regressor
model=LinearRegression()

#Train the model using the training set
model.fit(X_train, Y_train)
model.intercept_
#Converting the coefficient values to a dataframe
coeffcients = pd.DataFrame([X_train.columns,model.coef_]).T
coeffcients = coeffcients.rename(columns={0: 'Attribute', 1: 'Coefficients'})
coeffcients
"""
Model Evalutaion
"""
# Model Prediction on train data
Y_pred=model.predict(X_train)
# Model Evaluation
print('R^2:',metrics.r2_score(Y_train, Y_pred))
print('Adjusted R^2:',1 - (1-metrics.r2_score(Y_train, Y_pred))*(len(Y_train)-1)/(len(Y_train)-X_train.shape[1]-1))
print('MAE:',metrics.mean_absolute_error(Y_train, Y_pred))
print('MSE:',metrics.mean_squared_error(Y_train, Y_pred))
print('RMSE:',np.sqrt(metrics.mean_squared_error(Y_train, Y_pred)))
# Visualizing the differences between actual prices and predicted values
plt.scatter(Y_train, Y_pred)
plt.xlabel("Prices")
plt.ylabel("Predicted prices")
plt.title("Prices vs Predicted prices")
plt.show()
# Checking residuals
plt.scatter(Y_pred,Y_train-Y_pred)
plt.title("Predicted vs residuals")
plt.xlabel("Predicted")
plt.ylabel("Residuals")
plt.show()
# Checking Normality of errors
sns.distplot(Y_train-Y_pred)
plt.title("Histogram of Residuals")
plt.xlabel("Residuals")
plt.ylabel("Frequency")
plt.show()
"""
For Train Data
"""
# Predicting Test data with the model
y_test_pred = model.predict(X_test)
# Model Evaluation
acc_linreg = metrics.r2_score(Y_test, y_test_pred)
print('R^2:', acc_linreg)
print('Adjusted R^2:',1 - (1-metrics.r2_score(Y_test, y_test_pred))*(len(Y_test)-1)/(len(Y_test)-X_test.shape[1]-1))
print('MAE:',metrics.mean_absolute_error(Y_test, y_test_pred))
print('MSE:',metrics.mean_squared_error(Y_test, y_test_pred))
print('RMSE:',np.sqrt(metrics.mean_squared_error(Y_test, Y_test_pred)))