# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3 (ipykernel)
#     language: python
#     name: python3
# ---

# # Digital House - Data Science a Distancia
#
# ## Trabajo Práctico 2
#
#
#
# ### Autores: <NAME>, <NAME>, <NAME>, <NAME>, <NAME>
#
# <p style="text-align:right;">Mayo 2022</p>

# #### Aspectos técnicos
# La notebook se ejecuta correctamente en una instalación estándar de Anaconda versión 4.11.0 build  3.21.6, Python 3.9.7
#

# #### Librerías necesarias

import numpy as np
import pandas as pd
import re

# %matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
# from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# + tags=[]
import statsmodels.api as sm
# -

# Ignore some warnings
from warnings import simplefilter
simplefilter(action='ignore', category=FutureWarning)
simplefilter(action='ignore', category=UserWarning)

# ---
# #### Dataset

data_final_url = "../Data/properatti_final.csv"
data = pd.read_csv(data_final_url, encoding="utf-8")


# +
mask = data['state_name'] == 'Capital Federal'
mask = np.logical_and(mask, data['property_type'] == 'apartment')
data = data[mask].copy()

mask = data['place_name'] == 'Belgrano'
mask = np.logical_or(mask, data['place_name'] == 'Palermo')
mask = np.logical_or(mask, data['place_name'] == 'Recoleta')
data = data[mask].copy()

# -

# ---
# #### Seleccionar, renombrar y ajustar valores de las características

data.reset_index(inplace=True)

data.rename(columns={'property_type' : 'tipo'}, inplace=True)
data.rename(columns={'price_aprox_usd' : 'precio'}, inplace=True)
data.rename(columns={'surface_covered_in_m2' : 'superficie'}, inplace=True)

# Trabajar con precio en miles de dólares
data['precio'] = (data['precio'] / 1000).round(3)

# ---

data.shape

data.head()

data['place_name'].value_counts()

# ---
#

# +

sns.set()
plt.style.use('seaborn')

sns.mpl.rcParams['axes.titlesize'] = 20
sns.mpl.rcParams['axes.labelsize'] = 16


# + tags=[]
features = ['precio', 'superficie', 'cochera', 'pileta', 'parrilla']
# -

fig, ax = plt.subplots(figsize=(20, 8))
sns.heatmap(data[features].corr(), annot=True, vmin=-1, vmax=1, cmap='Oranges', ax=ax)
ax.set(title='Relación de características observadas')
plt.show()

fig, ax = plt.subplots(figsize=(16, 8))
sns.regplot(data=data, x='superficie', y='precio', ci=None, scatter_kws={'color':'r', 's':4}, ax=ax)
ax.set(title='Precio según Superficie Cubierta', 
       ylabel='Precio en Miles de dólares', 
       xlabel='Superficie Cubierta')
plt.show()

# + [markdown] tags=[]
# ---
# #### Variables calculadas
# -

data['logprecio'] = np.log(data['precio'])

fig, ax = plt.subplots(figsize=(16, 8))
sns.regplot(data=data, x='superficie', y='logprecio', ci=None, scatter_kws={'color':'r', 's':4}, ax=ax)
ax.set(title='Precio según Superficie Cubierta', 
       ylabel='Logaritmo del Precio en Miles de dólares', 
       xlabel='Superficie Cubierta')
plt.show()


# ---
#
#

# +
def train_LinearRegression(X, y) :
    u""" Performs Ordinary Least Squares linear regression
    
    one from Scikit-Learn linear models and two from statsmodels

    Args:
    * X array of array of features
    * y array of target values

    
    
    """
    
    Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, random_state=1)
    
    model = LinearRegression(fit_intercept=True)
    model.fit(Xtrain, ytrain)
    ypred = model.predict(Xtest)
    
    df = pd.DataFrame()
    df = pd.concat([df, pd.DataFrame(columns=['Features'], data=[ str(list(X.columns)) ] )], axis=1)

    df = pd.concat([df, pd.DataFrame(columns=['MAE'], data=[mean_absolute_error(ytest, ypred).round(3)] )], axis=1)
    df = pd.concat([df, pd.DataFrame(columns=['sqrt MSE'], data=[np.sqrt(mean_squared_error(ytest, ypred)).round(3)] )], axis=1)

    
    result_train = sm.OLS(ytrain, sm.add_constant(Xtrain)).fit()    
    r2a_train = result_train.rsquared_adj.round(3)

    result_test = sm.OLS(ytest, sm.add_constant(Xtest)).fit()    
    r2a_test = result_test.rsquared_adj.round(3)
    
    df = pd.concat([df, pd.DataFrame(columns=['R2 adj train'], data=[r2a_train] )], axis=1)
    df = pd.concat([df, pd.DataFrame(columns=['R2 adj test'], data=[r2a_test] )], axis=1)
    
    return model, df

    

# -

# ---
# ### Train models
#

pd.options.display.max_colwidth = 80

# +

y = data['logprecio']
metrics = pd.DataFrame()

data['s2'] = data['superficie'] ** 2


# +

X = data[['superficie']]
model, metric = train_LinearRegression(X, y)
metrics = metrics.append(metric)


# +

X = data[['superficie', 's2']]
model, metric = train_LinearRegression(X, y)
metrics = metrics.append(metric)


# +

X = data[['superficie', 's2','cochera']]
model, metric = train_LinearRegression(X, y)
metrics = metrics.append(metric)


# +

X = data[['superficie', 's2','pileta']]
model, metric = train_LinearRegression(X, y)
metrics = metrics.append(metric)


# +

X = data[['superficie', 's2','parrilla']]
model, metric = train_LinearRegression(X, y)
metrics = metrics.append(metric)


# +

X = data[['superficie', 's2','cochera', 'pileta']]
model, metric = train_LinearRegression(X, y)
metrics = metrics.append(metric)

# -

# ---

display(metrics.head(20))

fig, ax = plt.subplots(figsize=(12, 4))
sns.barplot(x=metrics['sqrt MSE'], y=metrics['Features'], palette='coolwarm', ax=ax)
ax.set(title='Evaluación de Métricas', 
       ylabel='Características', 
       xlabel='Raíz Cuadrada de la Media de Errores al Cuadrado')
plt.show()

fig, ax = plt.subplots(figsize=(12, 4))
sns.barplot(x=metrics['R2 adj test'], y=metrics['Features'], palette='coolwarm', ax=ax)
ax.set(title='Evaluación de Métricas', 
       ylabel='Características', 
       xlabel='R^2 Ajustado (evaluación)')
plt.show()

# departamento de 1 m2 cubierto sin cochera ni pileta
import math
my_X = [[70, 70*70, 0, 0]]
my_y = model.predict(my_X)[0]
display(my_y, math.exp(my_y))


# ---
# ### Gauss-Markov
#

# +
def gauss_markov_test(Xtest, ytest):
    u"""
    funcion para visualizar e identificar supuestos de linealidad sobre la regression lineal
    
    Args:
    * Xtest - bserverd features
    * ytest - observed values
    """
    
    model = sm.OLS(ytest, sm.add_constant(Xtest)).fit()
    
    display(model.summary())
    
    ypred = model.predict()
    resid = model.resid
    rstud = model.get_influence().resid_studentized_internal
    rsqrt = np.sqrt(np.abs(rstud))

    
    plt.figure(figsize=(16, 6))
    sns.regplot(x = ypred, y = ytest, lowess = True, line_kws = {'color': 'red'})
    plt.title('Linealidad de Valores Observados', fontdict = {'fontsize': 18})
    plt.xlabel('Valores Predecidos', fontdict = {'fontsize': 14})
    plt.ylabel('Valores Observados', fontdict = {'fontsize': 14})
    plt.show()

    plt.figure(figsize=(16, 6))
    sns.regplot(x = ypred, y = resid, lowess = True, line_kws = {'color': 'red'})
    plt.title('Linealidad de Residuos', fontdict = {'fontsize': 18})
    plt.xlabel('Valores Predecidos', fontdict = {'fontsize': 14})
    plt.ylabel('Residuos', fontdict = {'fontsize': 14})
    plt.show()
    
    plt.figure(figsize=(16, 8))
    sns.regplot(x = ypred, y = rsqrt, lowess = True, line_kws = {'color': 'red'})
    plt.title('Scale Location', fontdict = {'fontsize': 18})
    plt.xlabel('Valores Predecidos', fontdict = {'fontsize': 14})
    plt.ylabel('Residuos Normalizados', fontdict = {'fontsize': 14})
    plt.show()

    
    sns.mpl.rcParams['figure.figsize'] = (16, 8)
    fig, ax = plt.subplots(2)

    sm.graphics.tsa.plot_acf(x = resid, ax = ax[0], lags = 40 , alpha = 0.05, title = '')
    ax[0].set_title('Correlación de características', fontdict = {'fontsize': 18})

    plt.subplots_adjust(top = 1.5, wspace = 2)

    sm.ProbPlot(model.resid).qqplot(ax = ax[1], line = 's')
    ax[1].set_title('Normalidad de los Residuos', fontdict = {'fontsize': 18})
    ax[1].set_xlabel("Valores Teóricos", fontsize = 14)
    ax[1].set_ylabel("Valores Reales", fontsize = 14)
    plt.show()
    
    return


X = data[['superficie', 's2', 'cochera', 'pileta']]
y = data['logprecio']

gauss_markov_test(X, y)

# -

# ---



StarcoderdataJupyterScriptsDedupFiltered