#####################################################################
# Exemple de régression linéaire multiple
# étant donné un ensemble d'individus, connaissant leur nom,
# leur sexe, leur age, leur taille et leur poids, on se demande
# s'il est possible d'établir une relation linéaire qui permettrait
# de calculer le poids en fonction des autres données
#####################################################################


#####################################################################
# import des librairies
#####################################################################
from io import StringIO
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import statsmodels.api as sm
import sys
from mpl_toolkits.mplot3d import Axes3D

line = "=" * 50
separator = "\n" * 2

#####################################################################
# Données en entrée et en sortie
#####################################################################	

donnees = StringIO("""name,sex,age,size,weight
"Joey", 1,  25,   72,   178
"Jill", 0,  32,   68,   122
"Jack", 1,  27,   69,   167
"John", 1,  45,   67,   210
"Jane", 0,  38,   62,   108""")

#
# création d'un dataframe pandas
# qui permet de manipuler facilement les données
#
df = pd.read_csv(donnees, sep=",")

print(line)
print("Données initiales :")
print(line)
print( df.head() )

df = df.drop('name', axis=1)

#####################################################################
# On sépare les données en deux catégories :
# - les données ou rubriques (quantitatives et qualitatives) qui 
# 	définissent un individu
# - ce que l'on veut prédire, en l'occurrence, le poids
#####################################################################	

y = df.weight

# variables
variables_du_modele = df.columns.drop(['weight'])
X = df[ variables_du_modele ]
#X = X.astype(float)

print(separator)
print(line)
print("Rubriques pour chaque individu :")
print(line)
print(X)
print(line)
print("Poids à prédire :")
print(line)
print(y)

#####################################################################
# Matrice de corrélation
#####################################################################

#
# calcul de la matrice de corrélations
#
corr = X.corr()

#
# dessiner la matrice avec ses valeurs (annot=True)
#
sns.heatmap(
	corr, 
	cmap=sns.color_palette("YlOrRd", 10), 
	linewidths=.5,
	annot=True,
	xticklabels=corr.columns.values, 
	yticklabels=corr.columns.values
)
plt.title("Matrice de corrélation")
plt.show()

#####################################################################
# calcul de la régression
#####################################################################
modele = LinearRegression()
modele.fit( X, y)

# affiche les coefficients
print( "coefficients : ", modele.coef_ )
print( "constante    : ", modele.intercept_ )

y_prime = modele.predict( X )

print(separator)
print(line)
print("Poids prédits : ", y_prime)

# Affiche l'erreur
print('Erreur : %.2f' % mean_squared_error( y, y_prime) )
# Affiche r^2
print('r^2 %.2f' % r2_score(y, y_prime) )


#####################################################################
# Calcul des tests liés à la regression afin de valider le modèle
#####################################################################

X_stats = sm.add_constant( X ) 
stats = sm.OLS( y_prime, X_stats ).fit()
print( stats.summary() )

#####################################################################
# Affichage du résultat
#####################################################################

fig = plt.figure()
axes = fig.add_subplot(111, projection='3d')
plt.title("Données avant régression")
axe1 = X.age
axe2 = X.size
axes.scatter(axe1, axe2, y.astype(float).tolist(), c='green')
axes.scatter(axe1, axe2, y_prime.astype(float).tolist(), c='red', marker='D', alpha=0.5)
plt.show()


