Regresión lineal multiple

En este trabajo se usan datos provistos por Properati, los cuales tienen información sobre publiciones de propiedades ofrecidas en su sitio web; el dataset actual cuenta con distintos tipos de propiedades (Casa, Deparamento y PH), el barrio en donde se encuentra la propiedad y una descripción cuantitativa de la misma, como el número de habitaciones, la superficie, entre otras. Sobre este dataset se implementan varios modelos de regresión lineal multiple, con el fin de comparar y obtener el mejor módelo.

Librerías

library(tidyverse)
library(dplyr)
library(plyr)
library(tidyr)
library(ggplot2)
library(modelr)
library(lubridate)
library(knitr)
library(rmarkdown)
library(readr)
library(kableExtra)
library(ggcorrplot)
library(ggthemes)
library(GGally)
library(broom)

Lectura

El dataset se encuentra contenido en un archivo rds.Es necesario transformar algunas columnas como factores, y remover el id de las propiedades, ya que no será de útilidad durante el proceso.

## Leer el archivo contenido en formato rds
properties <- readRDS("ar_properties.rds")

## Modificar el tipo de propiedad y el barrio como factor
properties <- properties %>%
  mutate( property_type = factor(property_type),
          l3 = factor(l3))  %>%
  select( -c( id))

Es importante destacar que en todos los modelos implementados el intercepto carece de interpretación, puesto que este sería el precio promedio de una propiedad, con 0 habitaciones, 0 m2 de superficie, 0 baños, ETC. Por otro lado todos los modelos implementados corresponden a modelos de regresión lineal múltiple, por ello la interpretación de los coeficientes está ligada al cambio esperado en la estimación cuando el resto de las variables permanecen constantes. ## Modelo 1:

\[ price = intercept + \beta_1 (rooms) + \beta_2(bathrooms) + \beta_3(surface\_total) + \beta_4(surface\_covered) + \\ \beta_5(property\_type\_Departamento) + \beta_6(property\_type\_PH) + \beta_7(barrio) + \varepsilon\]

Este primer modelo usa todas las variables del dataset, en el caso de las variables categóricas cada categoría es tomada como una variable dummy, omitiendo la primer categoría (alfabéticamente), con el fin de evitar problemas de colinealidad, es decir, en una variable categorica con n diferentes categorías, se tendrán n-1 variables dummies; la categoría faltante está dado por un 0 en las n-1 dummies.

## Armamos el modelo para predecir el precio con todas las variables
rl_model<-lm(price ~  ., data = properties)

## Imprimimos los coeficientes del modelo
summary(rl_model)
## 
## Call:
## lm(formula = price ~ ., data = properties)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -400904  -33817   -3307   24660  560915 
## 
## Coefficients:
##                             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)               -109406.61    4788.67 -22.847  < 2e-16 ***
## l3Agronomía                   623.53    8846.14   0.070 0.943807    
## l3Almagro                   -4520.04    4295.24  -1.052 0.292650    
## l3Balvanera                -24788.27    4551.65  -5.446 5.18e-08 ***
## l3Barracas                 -10128.24    5351.06  -1.893 0.058397 .  
## l3Barrio Norte              49921.81    4417.82  11.300  < 2e-16 ***
## l3Belgrano                  69648.12    4283.55  16.259  < 2e-16 ***
## l3Boca                     -47540.60    7076.20  -6.718 1.86e-11 ***
## l3Boedo                    -19034.38    5219.54  -3.647 0.000266 ***
## l3Caballito                  6220.15    4301.29   1.446 0.148153    
## l3Catalinas                -76321.95   33563.74  -2.274 0.022974 *  
## l3Centro / Microcentro     -29046.49    6781.80  -4.283 1.85e-05 ***
## l3Chacarita                 11903.39    5299.02   2.246 0.024687 *  
## l3Coghlan                   40820.55    5462.90   7.472 8.02e-14 ***
## l3Colegiales                34073.02    4816.54   7.074 1.52e-12 ***
## l3Congreso                 -32314.97    5494.75  -5.881 4.10e-09 ***
## l3Constitución             -47292.98    6321.63  -7.481 7.50e-14 ***
## l3Flores                   -22510.27    4536.15  -4.962 6.99e-07 ***
## l3Floresta                 -28315.65    5069.38  -5.586 2.34e-08 ***
## l3Las Cañitas               90455.90    5883.38  15.375  < 2e-16 ***
## l3Liniers                  -20080.34    5366.27  -3.742 0.000183 ***
## l3Mataderos                -33863.43    5424.79  -6.242 4.35e-10 ***
## l3Monserrat                -32431.49    5228.46  -6.203 5.59e-10 ***
## l3Monte Castro              -8770.72    5949.63  -1.474 0.140445    
## l3Nuñez                     56958.42    4559.69  12.492  < 2e-16 ***
## l3Once                     -30757.83    5456.51  -5.637 1.74e-08 ***
## l3Palermo                   66169.58    4221.50  15.674  < 2e-16 ***
## l3Parque Avellaneda        -34398.95    7598.09  -4.527 5.99e-06 ***
## l3Parque Centenario        -12288.30    5016.45  -2.450 0.014305 *  
## l3Parque Chacabuco         -22537.83    5314.36  -4.241 2.23e-05 ***
## l3Parque Chas                5195.26    7542.97   0.689 0.490981    
## l3Parque Patricios         -36808.02    5973.29  -6.162 7.24e-10 ***
## l3Paternal                 -13314.50    5189.69  -2.566 0.010304 *  
## l3Pompeya                  -79977.17    8035.74  -9.953  < 2e-16 ***
## l3Puerto Madero            259015.83    5095.12  50.836  < 2e-16 ***
## l3Recoleta                  64088.22    4360.34  14.698  < 2e-16 ***
## l3Retiro                    26067.40    5281.27   4.936 8.01e-07 ***
## l3Saavedra                  19492.00    4914.18   3.966 7.31e-05 ***
## l3San Cristobal            -23739.75    4955.13  -4.791 1.67e-06 ***
## l3San Nicolás              -26247.55    5168.96  -5.078 3.83e-07 ***
## l3San Telmo                 -5653.85    4877.12  -1.159 0.246356    
## l3Tribunales               -34608.17    8924.63  -3.878 0.000106 ***
## l3Velez Sarsfield          -25943.69    8303.75  -3.124 0.001783 ** 
## l3Versalles                -22232.13    6758.40  -3.290 0.001004 ** 
## l3Villa Crespo               1595.26    4317.54   0.369 0.711770    
## l3Villa del Parque          -3290.17    4866.59  -0.676 0.498997    
## l3Villa Devoto              13301.39    4807.08   2.767 0.005659 ** 
## l3Villa General Mitre      -19170.08    6802.25  -2.818 0.004831 ** 
## l3Villa Lugano             -83039.18    6533.35 -12.710  < 2e-16 ***
## l3Villa Luro                -7579.11    5404.78  -1.402 0.160833    
## l3Villa Ortuzar             18667.61    6829.18   2.734 0.006269 ** 
## l3Villa Pueyrredón          10516.80    5349.56   1.966 0.049314 *  
## l3Villa Real                -8823.37    8745.56  -1.009 0.313030    
## l3Villa Riachuelo          -32775.66   17171.10  -1.909 0.056298 .  
## l3Villa Santa Rita          -5767.71    6383.86  -0.903 0.366274    
## l3Villa Soldati           -136489.91   18944.29  -7.205 5.90e-13 ***
## l3Villa Urquiza             30648.43    4418.91   6.936 4.09e-12 ***
## rooms                       -3961.27     444.58  -8.910  < 2e-16 ***
## bathrooms                   34040.98     644.28  52.836  < 2e-16 ***
## surface_total                 919.08      23.52  39.069  < 2e-16 ***
## surface_covered              1457.18      28.73  50.715  < 2e-16 ***
## property_typeDepartamento   92653.32    2191.23  42.284  < 2e-16 ***
## property_typePH             46779.37    2274.94  20.563  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 66580 on 45841 degrees of freedom
## Multiple R-squared:  0.7764, Adjusted R-squared:  0.7761 
## F-statistic:  2568 on 62 and 45841 DF,  p-value: < 2.2e-16

Se puede observar que todas las variables cuantitativas son estadísticamente significativas. El coeficiente de cada una de estas índica como cambia el precio pronósticado en función del aumento en cada unidad cuando el resto de las variables están constantes, por ejemplo, por cada baño que tenga la propiedad, la estimación del precio aumenta 34,041 USD; el signo de cada coeficiente índica como varía el precio estimado, por ejemplo, en el caso del número de ambientes, por cada ambiente que tenga la propiedad el precio estimado disminuye 3,962 USD.

En el caso del tipo de propiedades, los departamentos son los que más incrementan el precio estimado por el modelo, 92,654 USD; seguido por los PH con 46,780 USD y finalmente las casas (representadas por un 0 en la varaible dummy de departamento y en la variable dummy de PH). El signo negativo en la variable rooms probablemente esté ligado a este factor, las casas son las que menos costo tienen, y a su vez las casas se caracterizan por tener una cantidad mayor de ambientes.

Por otro lado los barrios presentan una mayor cantidad de categorías (57), por lo cual hay categorías con una frecuencia muy baja. En este caso el barrio Abasto se representa cuando las 56 variables dummies de l3 presentan valor en 0. Hay varias barrios como Agronomía, Almagro, Caballito, entre otras; que no son significativas, ya que tienen un p-value muy alto , por lo cual en estas no se puede rechazar la hipótesis nula y no se puede afirmar que existe relación líneal entre estas categrorías y la variable estimada (precio).

El R2 ajustado en este caso es de 0.7761 esto quiere decir que el modelo logra captar el 77.6% de la variabilidad de la variable respuesta (precio). Por otro lado el p-value general del modelo permite rechazar la hipótesis nula, la hipótesis de que un modelo con solo intercepción y el actual modelo son lo mismo, es decir, esta hipótesis asume que las variables adicionales no proporcionan valor adicional en conjunto; como se rechaza índica que el modelo actual es mejor, que las variables adicionales hacen que este modelo sea significativamente mejor.

Ecuación modelo

\[ price = \\ -109,406.61 - 3,961.27(rooms) + 34,040.98(bathrooms) + 919.08(surface\_total) \\+ 1,457.18(surface\_covered) + 92,653.32(property\_type\_Departamento) + 46,779.37(property\_type-PH) \\ + barrio... + \varepsilon\]

Ejemplos de pronóstico:

  • Caso 1: Un departamento de 120 mts cuadrados cubiertos en abasto, con 3 dormitorios y 2 baños
  • Caso 2: Un PH en Balvanera, con 80 mts cuadrados cubiertos, 20 mts cuadrados no cubiertos, 2 dormitorios y 3 baños.
## Generar un df con dos registros, uno por cada caso
pronostico = data.frame(
    rooms = c(3,2),
    bathrooms=c(2,3),
    surface_total=c(120,80),
    surface_covered=c(120,100), 
    l3 = c("Abasto", "Balvanera"), 
    property_type=c("Departamento","PH"))

## Predecir con el modelo generado tomando el df
predict(rl_model, pronostico)
##        1        2 
## 324596.4 226029.5

El modelo estima una precio de 324,596 USD para el caso 1 y un precio de 226,029 USD para el caso 2. Por lo cual según la estimación del modelo, el precio sería mayor para el caso 1: Un departamento de 120 mts cuadrados cubiertos en abasto, con 3 dormitorios y 2 baños.

Modelo 2:

\[ price = intercept + \beta_1 (rooms) + \beta_2(bathrooms) + \beta_3(surface\_total) + \beta_4(surface\_covered) + \\ \beta_5(property\_type\_Departamento) + \beta_6(property\_type\_PH) + \varepsilon \]

Para este segundo modelo se excluye el barrio del modelo a implementar, el resto de variables se toman de la misma manera que en el modelo anterior.

## Omitir barrio del df
properties_tratado <-  properties %>% select( -c(l3))

## Armamos el modelo para predecir el precio con todas las variables
rl_model<-lm(price ~  ., data = properties_tratado)

## Imprimimos los coeficientes del modelo
summary(rl_model)
## 
## Call:
## lm(formula = price ~ ., data = properties_tratado)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -518799  -36177   -9643   25740  724251 
## 
## Coefficients:
##                             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)               -131096.86    2750.50  -47.66   <2e-16 ***
## rooms                      -13348.53     519.02  -25.72   <2e-16 ***
## bathrooms                   42664.68     756.37   56.41   <2e-16 ***
## surface_total                 877.03      27.59   31.79   <2e-16 ***
## surface_covered              1783.80      33.53   53.21   <2e-16 ***
## property_typeDepartamento  135177.47    2513.93   53.77   <2e-16 ***
## property_typePH             68598.52    2677.46   25.62   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 79210 on 45897 degrees of freedom
## Multiple R-squared:  0.6832, Adjusted R-squared:  0.6831 
## F-statistic: 1.649e+04 on 6 and 45897 DF,  p-value: < 2.2e-16

En este casos todas las variables del modelo son significativas. Los coeficientes del tipo de propiedad se mantienen en cuanto a orden, es decir, mayor precio para los departamentos, segudio de los PH y finalmente las casas. Por otro el aumento en los baños sigue siendo el de mayor peso en cuanto a las variables cuantitativas de la propiedad. El R2 ajustado índica que el modelo explica el 68.3% de la variabiliad de la variable respuesta. En cuanto al estadístico F de nuevo se rechaza la hipótesis nula, por lo cual el modelo actual es mejor que un modelo con solo intercepción.

El R2 ajustado es menor al módelo anterior, esto valida la importancia de la ubicación de la propiedad al momento de estimar el precio, ya que este modelo asume que dos propieades identicas en cuanto a tipo y características tendrán el mismo precio en todas las zonas, algo que evidentemente no es cierto.

Modelo 3:

\[ price = intercept + \beta_1 (rooms) + \beta_2(bathrooms) + \beta_3(surface\_total) + \beta_4(surface\_covered) + \\ \beta_5(property\_type\_Departamento) + \beta_6(property\_type\_PH) + \beta_7(Barrio\_Low) + \beta_8(Barrio\_Medium) + \varepsilon \]

Como se corroboró al comparar los dos primeros modelos, la ubicación de la propiedad es importante a la hora de ajustar el precio a través de un modelo. Es por ello, que en este modelo se propone retomar la ubicación de las propiedades, pero para disminuir la gran cantidad de categorías que tiene la variable barrio, se agrupan en tres categorías. Los barrios se agruparon en tres categorías, basandose en el precio promedio del m2 de las propieadades de los barrios:

## Precio promedio por barrio del m2
mean_barrio <- ddply(properties, ~l3, summarise, 
                     mean_price = mean( price/surface_total ))

## Graficar el precio ordenado 
mean_barrio %>%
  mutate(l3 = fct_reorder(l3, mean_price, .desc = TRUE)) %>%
  ggplot(aes(x = l3, y = mean_price)) +
  geom_bar(stat = 'identity', aes(color = l3), show.legend = FALSE) + coord_flip() +
  geom_hline(yintercept = 2200, color='coral', size=1)  +
  geom_hline(yintercept = 2900, color='coral', size=1) 

Con base a lo observado en la gráfica se proponen tres agrupaciones:

\[ precio\_promedio $=<$ 2,200 --> LOW \]

\[ 2,200 < precio\_promedio $=<$ 2,900 --> MEDIUM \]

\[ precio\_promedio $>$ 2,900 --> HIGH \]

A continuación se presentan los barrios que quedaron en cada categoría, junto a la cantidad de propiedades en el mismo. Dicha agrupación es coherente en cuanto a los barrios presentes en cada categoría.

## Generar las categorías generadas sobre el precio promedio de m2 por barrio
mean_barrio <- mean_barrio %>%
  mutate(Barrios = case_when(mean_price > 2900 ~ 'High',
                             mean_price > 2200 ~ 'Mid',
                             TRUE ~ 'Low'))

## Añadir la agrupación de precio generada al df original, y convertirla como factor
properties_tratado <- properties %>% 
                inner_join(.,mean_barrio, by = "l3") %>%
                mutate(Barrios = factor(Barrios))

## Observar los barrios de precio de m2 alto, con cant. de propiedades en ese barrio
properties_tratado %>%
              filter(Barrios=='High') %>%
              group_by(l3) %>%
              summarise(Barrio = count(l3))
##        Barrio.x Barrio.freq
## 1  Barrio Norte        1916
## 2      Belgrano        3939
## 3   Las Cañitas         256
## 4         Nuñez        1233
## 5       Palermo        7104
## 6 Puerto Madero         517
## 7      Recoleta        2554
## 8        Retiro         417
## Observar los barrios de precio de m2 alto, con cant. de propiedades en ese barrio
properties_tratado %>%
              filter(Barrios=='Mid') %>%
              group_by(l3) %>%
              summarise(Barrio = count(l3))     
##                Barrio.x Barrio.freq
## 1                Abasto         258
## 2               Almagro        3526
## 3              Barracas         389
## 4             Caballito        3403
## 5  Centro / Microcentro         154
## 6             Chacarita         408
## 7               Coghlan         351
## 8            Colegiales         740
## 9     Parque Centenario         557
## 10          Parque Chas         112
## 11             Paternal         459
## 12             Saavedra         642
## 13          San Nicolás         466
## 14            San Telmo         675
## 15         Villa Crespo        3056
## 16     Villa del Parque         690
## 17         Villa Devoto         769
## 18           Villa Luro         370
## 19        Villa Ortuzar         151
## 20     Villa Pueyrredón         393
## 21        Villa Urquiza        1913
## Observar los barrios de precio de m2 alto, con cant. de propiedades en ese barrio
properties_tratado %>%
              filter(Barrios=='Low') %>%
              group_by(l3) %>%
              summarise(Barrio = count(l3))     
##               Barrio.x Barrio.freq
## 1            Agronomía          73
## 2            Balvanera        1263
## 3                 Boca         135
## 4                Boedo         444
## 5            Catalinas           4
## 6             Congreso         341
## 7         Constitución         195
## 8               Flores        1321
## 9             Floresta         526
## 10             Liniers         386
## 11           Mataderos         370
## 12           Monserrat         438
## 13        Monte Castro         245
## 14                Once         354
## 15   Parque Avellaneda         110
## 16    Parque Chacabuco         405
## 17    Parque Patricios         241
## 18             Pompeya          95
## 19       San Cristobal         604
## 20          Tribunales          71
## 21     Velez Sarsfield          86
## 22           Versalles         157
## 23 Villa General Mitre         153
## 24        Villa Lugano         176
## 25          Villa Real          75
## 26     Villa Riachuelo          16
## 27    Villa Santa Rita         189
## 28       Villa Soldati          13
## Remover el barrio y el precio promedio del m2 en el mismo
properties_tratado <-  properties_tratado %>% 
                                  select( -c(l3, mean_price))

## Armamos el modelo para predecir el precio con todas las variables
rl_model<-lm(price ~  ., data = properties_tratado)

# Imprimimos los coeficientes del modelo
summary(rl_model)
## 
## Call:
## lm(formula = price ~ ., data = properties_tratado)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -421424  -36334   -4588   25287  685649 
## 
## Coefficients:
##                            Estimate Std. Error t value Pr(>|t|)    
## (Intercept)               -40533.59    2592.44  -15.63   <2e-16 ***
## rooms                      -7718.68     465.83  -16.57   <2e-16 ***
## bathrooms                  36979.39     677.19   54.61   <2e-16 ***
## surface_total                960.74      24.62   39.03   <2e-16 ***
## surface_covered             1474.98      30.05   49.09   <2e-16 ***
## property_typeDepartamento  93938.22    2275.00   41.29   <2e-16 ***
## property_typePH            48678.91    2395.66   20.32   <2e-16 ***
## BarriosLow                -95418.93     968.30  -98.54   <2e-16 ***
## BarriosMid                -63388.11     750.51  -84.46   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 70650 on 45895 degrees of freedom
## Multiple R-squared:  0.748,  Adjusted R-squared:  0.7479 
## F-statistic: 1.703e+04 on 8 and 45895 DF,  p-value: < 2.2e-16

Todas las variables del modelo son significativas, en cuanto a la inclusión de la agrupación por barrios, los coeficientes obtenidos concuerdan con la agrupación hecha, es decir, el menor coeficiente corresponde a la catergoría ‘Low’, seguido por ‘Medium’ y finalmente el coeficiente más alto ‘High’. El resto de variables conservan el comportamiento observado en los anteriores modelos.

Se obtiene un R2 ajustado que índica que el modelo capta el 74.8 de la variabilidad de la variable respuesta (precio). El estadístico F de nuevo rechaza la hipótesis nula, así que este modelo es mejor que un modelo basado en el intercepto unicamente.

Si bien este modelo está en alrededor de un 4% por debajo del primer modelo, en cuanto a variabilidad explicada, es importante mencionar dos aspectos favorables de este planteamiento; en este modelo todas las variables usadas son significativas, en el primero no; adicionalmente en este modelo, el agrupar los 57 barrios en tres categorías, facilita la lectura y explicación de los resultados.

Modelo 4:

\[ price = intercept + \beta_1 (rooms) + \beta_2(bathrooms) + \beta_3(surface\_Patio) + \beta_4(surface\_covered) + \\ \beta_5(property\_type\_Departamento) + \beta_6(property\_type\_PH) + \beta_7(Barrio\_Low) + \beta_8(Barrio\_Medium) + \varepsilon \]

En el dataset existen dos variables asociadas a la superficie de las propiedades, es por ello que se procede a validar la asociación entre las dos variables.

## Grafico de dispersión entre sup. cubierta y sup. total junto a una linea de suvizado
ggplot(properties, aes(x=surface_covered, y=surface_total)) +   
  geom_point(aes(col=property_type)) +                        
  geom_smooth(method="lm")    +                             
  labs(y="Superficie total", 
       x="Superficie cubierta", 
       title="")

## Imprimir casos en que la sup.cubierta > sup. total
properties %>% filter(surface_covered > surface_total)
## # A tibble: 0 x 7
## # ... with 7 variables: l3 <fct>, rooms <dbl>, bathrooms <dbl>,
## #   surface_total <dbl>, surface_covered <dbl>, price <dbl>,
## #   property_type <fct>

Es evidente que existe una correlación lineal entre las variables, casi que perfecta. A través del gráfico de dispersión se puede observar que el valor en Y es mayor al valor de X, algo que se esperaba, ya que no sería lógico que la superficie cubierta fuera mayor a la superficie total. De igual modo al filtrar el dataset se valida que efectivamente no existen registros de esta forma.

Como las variables se encuentran correlacionadas, se opta por calcular una nueva variable que exprese de mejor manera la diferencia entre estas, es decir, que represente la superficie descubierta de la propiedad.

## Añadir nueva variable con la resta, incluir la categoría de barrios calculada anteriormente y remover variables que no se usan
properties_tratado <- properties  %>%
            mutate(surface_patio  = surface_total - surface_covered ) %>% 
            inner_join(.,mean_barrio, by = "l3") %>% 
            mutate(Barrios = factor(Barrios)) %>% 
            select( -c(l3,  surface_total, mean_price))

## Armamos el modelo para predecir el precio con todas las variables
rl_model<-lm(price ~  ., data = properties_tratado)

# Imprimimos los coeficientes del modelo
summary(rl_model)
## 
## Call:
## lm(formula = price ~ ., data = properties_tratado)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -421424  -36334   -4588   25287  685649 
## 
## Coefficients:
##                            Estimate Std. Error t value Pr(>|t|)    
## (Intercept)               -40533.59    2592.44  -15.63   <2e-16 ***
## rooms                      -7718.68     465.83  -16.57   <2e-16 ***
## bathrooms                  36979.39     677.19   54.61   <2e-16 ***
## surface_covered             2435.72      15.88  153.40   <2e-16 ***
## property_typeDepartamento  93938.22    2275.00   41.29   <2e-16 ***
## property_typePH            48678.91    2395.66   20.32   <2e-16 ***
## surface_patio                960.74      24.62   39.03   <2e-16 ***
## BarriosLow                -95418.93     968.30  -98.54   <2e-16 ***
## BarriosMid                -63388.11     750.51  -84.46   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 70650 on 45895 degrees of freedom
## Multiple R-squared:  0.748,  Adjusted R-squared:  0.7479 
## F-statistic: 1.703e+04 on 8 and 45895 DF,  p-value: < 2.2e-16

En este modelo nuevamente todas las variables son significativas, incluyendo la variable generada. Se mantiene el orden de las categorías tanto en tipos de propiedad como en barrio, algo que va de la mano con los modelos vistos anteriormente.

Este modelo logra explicar el 74.8% de la variabilidad de la variable respuesta, es decir, el mismo porcentaje del anterior modelo. De igual manera en el estadístico F se rechaza la hipótesis nula.

Si bien este modelo no supera el modelo anterior, es importante destacar que este modelo logra alcanzar una alta variabilidad, y evita la presencia de dos variables directamente correlacionadas en el modelo, generando una nueva variable que explica de mejor manera la descripción de la propiedad.

Análisis residuos

  • El primer gráfico muestra los residuos vs los valores ajustados por el modelo, acá se podrían identificar patrones no lineales en los datos que los modelos no logran captar; sin embargo en este caso se presenta lo esperado, residuos distribuidos equitativamente al rededor de la linea casi horizontal, sin patrones, como una nube.
  • El segundo gráfico (QQplot) muestra si los residuos tienen ditribución normal estándarizada, esto se evidencia a través de la alineación con respecto a la recta; en este caso se ven valores alejados de la recta, tanto a la izquierda como a la derecha. Sin embargo, se cuentan con suficientes observaciones y por el teórema central del límite se espera que los estimadores asociados a los coeficientes estarán aproximadamente distribuidos normalmente, que es lo que se necesita para construir intervalos de confianza y hacer pruebas de hipótesis. En un supesto caso de no contar con suficiente datos, sería necesario hacer remuestreo sobre los datos o usar un modelo lineal generalizado.
  • El tercer gráfico permite observar si los residuos se distribuyen por igual a lo largo del rango de la variable estimada, validando el supuesto de igual varianza (homocedasticidad). En este caso se observa una línea inclinada y con un ángulo pronunciado, donde los residuos van incrementando a medida que aumentan los valores estimados, no se da por cumplido el supuesto de homocedasticidad.
  • El cuarto gráfico evidencia la presencia de observaciones influyenes (en caso de existir), ya que no todos los valores atípicos influyen en el análisis de regresión. En este caso no hay puntos fuera de la distancia de Cook, por lo cual, se descarta la presencia de valores influyentes en el modelo.
plot(rl_model)

Modelo 5:

\[ \log(price) = intercept + \beta_1 \log(rooms) + \beta_2\log(bathrooms) + \beta_3(surface\_Patio) + \beta_4\log(surface\_covered) + \\ \beta_5(property\_type\_Departamento) + \beta_6(property\_type\_PH) + \beta_7(Barrio\_Low) + \beta_8(Barrio\_Medium) + \varepsilon \]

Ahora se procede a validar la utilidad de una estandarización en las variables continuas, y verificar si las unidades de las variables afectan el modelo. Para ello se toma como base el modelo 4, implementado anteriormene.

Esta normalización mediante el logaritmo permite que los valores chicos se se expandan, mientras que los valores más grandes son comprimidos, este proceso ayuda a obtener una distribución normal en los datos.

## Calcular las variables trasnformadas, añadir la agrupación de barrios y remover variables
properties_tratado <- properties %>%
    mutate(surface_patio  = surface_total - surface_covered ,
           log_price = log(price),
           log_rooms = log(rooms),
           log_bathrooms = log(bathrooms),
           log_surface_covered = log(surface_covered))  %>% 
    inner_join(.,mean_barrio, by = "l3") %>% 
    mutate(Barrios = factor(Barrios)) %>%
    select( -c(l3,  surface_total, price, rooms, mean_price, bathrooms, surface_covered))

## Armamos el modelo para predecir el precio con todas las variables
rl_model<-lm(log_price ~  ., data = properties_tratado)

# Imprimimos los coeficientes del modelo
summary(rl_model)
## 
## Call:
## lm(formula = log_price ~ ., data = properties_tratado)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.34564 -0.14880 -0.00853  0.13958  1.33820 
## 
## Coefficients:
##                             Estimate Std. Error  t value Pr(>|t|)    
## (Intercept)                8.789e+00  1.893e-02  464.264  < 2e-16 ***
## property_typeDepartamento  2.067e-01  7.251e-03   28.507  < 2e-16 ***
## property_typePH            5.359e-02  7.670e-03    6.987 2.85e-12 ***
## surface_patio              4.205e-03  7.983e-05   52.678  < 2e-16 ***
## log_rooms                 -3.256e-02  3.794e-03   -8.581  < 2e-16 ***
## log_bathrooms              1.849e-01  3.819e-03   48.401  < 2e-16 ***
## log_surface_covered        7.930e-01  4.470e-03  177.403  < 2e-16 ***
## BarriosLow                -4.438e-01  3.133e-03 -141.651  < 2e-16 ***
## BarriosMid                -2.517e-01  2.427e-03 -103.675  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2285 on 45895 degrees of freedom
## Multiple R-squared:  0.8201, Adjusted R-squared:  0.8201 
## F-statistic: 2.616e+04 on 8 and 45895 DF,  p-value: < 2.2e-16

Las variables normalizadas y todas las variables que no se modificaron son significativas. Las categorías generadas mantienen el orden logico y presentado en los modelos anteriores. Pero lo más importante es que el R2 ajustado mejoró, en este nuevo modelo se logra captar un 82% de la variabilidad. El estadístico F una vez más rechaza la hipótesis nula, por lo cual este nuevo modelo es mejor que un modelo basado unicamente en la intercepción.

Este incremento en los resultados índica que la transformación realizada sobre los datos mejora el comportamiento del modelo, las variables originales presentaban valores muy dispersos y en algunos casos muy extremos, ya que estaban influenciados por las unidades, al eliminar dichas unidades el modelo logra captar de mejor manera la variabilidad.

Modelo 6:

\[ price = intercept + \beta_1 (rooms) + \beta_2(bathrooms) + \beta_3(surface\_Patio) + \beta_4(surface\_covered) + \\ \beta_5(property\_type) + \beta_6(Barrio\_Low) + \beta_7(Barrio\_Medium) + \varepsilon\]

Es posible que cada tipo de propiead tenga un comportamiento diferente, es por ello que se opta por implementar un modelo para cada tipo de propiedad, y de esta manera evaluar si esto mejora los resultados o no, ya que es evidente que se presenta un desbalanceo en los datos, donde cerca del 88% de las propiedades corresponden a departamentos.

## Añadir nueva variable con la resta, incluir la categoría de barrios calculada anteriormente y remover variables que no se usan
properties_tratado <- properties  %>%
            mutate(surface_patio  = surface_total - surface_covered ) %>% 
            inner_join(.,mean_barrio, by = "l3") %>% 
            mutate(Barrios = factor(Barrios)) %>% 
            select( -c(l3,  surface_total, mean_price))


## Generar función con el modelo a aplicar
type_model <- function(df) 
  {
  lm(price ~  ., data = df)
}

## Anidar por tipo de propiedad
properties_types <- properties_tratado %>% 
  group_by(property_type) %>% 
  nest()

## Aplicar a cada anidado el modelo
properties_types <- properties_types %>% 
  mutate(model = map(data, type_model))

## Liberar los resultados de cada modelo
glnc <- properties_types %>% 
  mutate(glnc = map(model, glance)) %>% 
  unnest(glnc, .drop = TRUE) %>% 
  select(-c('data','model','df'))
paged_table(glnc)
## Imprimir coeficientes de cada modelo
tdy <- properties_types %>% 
  mutate(tdy = map(model, tidy)) %>% 
  unnest(tdy, .drop = TRUE)%>% 
  select(-c('data','model'))

paged_table(tdy)

En el primer modelo sobre los departamentos, todas las variables son significativas. El R2 ajustado es de 77.5%, aun cuando la mayoría de propiedades son departamentos, el modelo actual no logra superar los modelos previos, sin embargo presenta un buen comportamiento; como en los modelos anteriores este modelo presenta un estadístico F que rechaza la hipótesis nula.

De igual modo los coeficientes de las categorías generadas al agrupar por barrios, son coherentes con la agrupación, es decir, el coeficiente de mayor valor son los barrios ‘High’, seguido por ‘Medium’ y finalmente ‘Low’.

El modelo de regresión para las casas arroja todas las variables significativas, pero un R2 ajustado que capta solo el 59% de la varaibilidad de la varible respuesta, aun siendo menor, presenta un estadístico F que permite rechazar la hipótesis nula, y comprobar que este modelo es mejor a uno basado unicamente en intercepción. Los coeficientes del barrio concuerdan con la agrupación establecida. Por otro lado, en este modelo el coeficiente de rooms es positvo, algo que hasta ahora no había pasado en los anteriores modelos.

Para este caso de los PH, no todas las variables son significativas, la variable rooms presenta un p-value muy alto, por lo cual no se puede rechazar la hipótesis nula, por lo cual no existe evidencia para afirmar que hay una relación lineal entre el número de ambientes y el precio de los PH; del mismo modo el error cuadrado de este coeficiente es incluso mayor que el mismo coeficiente, así que si se ejecuta varias veces este modelo, este coeficiente podría variar en cada ejecución. En cuanto al R2 ajustado de este modelo es del 68.8%, y el estadístico F índica que es el modelo es mejor que solo el intercepto.

Al validar los tres modelos de manera separada, se puede evidenciar que un unico modelo que agrupe los tres tipos de propieades presenta mejor comportamiento, es decir, el rendimiento no incrementó al dividir el estudio en un modelo por cada tipo de propiedad.

Mejor modelo

A continuación se consolidan los R2 ajustados obtenidos en los diferentes modelos.

Modelo R2_ajustado
Modelo 1 0.7761
Modelo 2 0.6831
Modelo 3 0.7479
Modelo 4 0.7479
Modelo 5 0.8201
Modelo 6
Dptos. 0.775
Casas 0.5884
PHs 0.6874

El mejor modelo implmentado fue el 5° modelo:

\[ \log(price) = 8.746 - 0.038 \log(rooms) + 0.19\log(bathrooms) + 0.004(surface\_Patio) + 0.8\log(surface\_covered) + \\ 0.24(property\_type\_Departamento) + 0.08(property\_type\_PH) - 0.46(Barrio\_Low) - 0.27(Barrio\_Medium) + \varepsilon\]

Para predicciones que se realicen sobre este modelo, es importante tener en cuenta que el resultado estará dado en función del logaritmo natural, si se quiere recuperar el precio en dólares se debe realizar el siguiente calculo:

\[ e^{\log(price)} = price \]

Parameter Interpretation
Residuals
Residuals Los residuos son la diferencia entre los valores de respuesta reales (precio), y los valores de respuesta pronósticados por el módelo. Se busca que estos tengan una distribución normal, con promedio en 0. Y esto es lo que pasa en el modelo, cómo se observa en el histograma.
Coefficients
Estimate

El intercepto, es decir el valor de origen de la recta donde se cruza con el eje vertical es de 8.746, este es el monto de partida de la recta modelada. El valor esperado del precio de una propiedad cuando todas las variables preditoras son 0. Sin embargo como se mencionó anteriormente, no representa mucha utilidad ya que todas las variables deben ser 0 y no hay casas de 0 m2.

En cuanto a los coeficientes de las restantes variables como se mencionó anteriormente, la interpretación de cada uno está ligada a como altera su cambio cuando las demas variables están constantes. En el caso de coeficientes de variables como log_rooms, log_bathrooms y log_surface_covered, se puede concluir que se espera un cambio porcentual en el precio cuando las variables cambien por algún porcentaje. Por ejemplo la elasticidad de la variable rooms es -0.038, así que un incremento del 1% en la cantidad de habitaciones terminará en un decremento del 0.038% en el precio estimado de la propiedad. De manera similar en los baños, cuya elasticidad es de 0.19, por cada incremento del 1% en bathrooms el precio estimado aumentará un 19%. En el caso de las variables que no fueron transformadas, como la superficie del patio, el precio estimado incrementará un 0.4% por cada m2 adicional que tenga la propiedad. En el caso de las variables dummies como los tipos de propiedad, por ejemplo si la propiedad está en barrio catalogado como ‘Bajo’ se espera que el precio estimado dismunuya un 46%; si es un departamento el precio estimado incrementa un 24%.
Std. Error Mide la cantidad promedio de las variación en las estimaciones de cada coeficiente, es decir, la precisión con la que el módelo estima el valor desconcido del coeficiente. Sirve para ver que tanto varía el modelo con distintas ejecuciones. En este caso el promedio del desvío de los coeficientes es del 1% algo ideal, ya que esto asegura que el modelo se ajusta.
T-Valor Es una medida de cuantas desviaciones estándar el coeficiente estimado está lejos de 0. Lo ideal es que esté muy lejos de 0, ya que esto indicaría que es posible rechazar la hipótesis nula, es decir, de declarar una relación entre la variable respuesta y cada predictor. En nuestro ejemplo, los valores de la estadística t están relativamente lejos de cero y son grandes en relación con el error estándar, lo que podría indicar que existe una relación.
P-Value Tres estrellas representan altamente significativas. Es decir, en todas las variables se puede rechazar la hipótesis nula, lo que índica que existe una relación entre cada predictor y la variable respesta (precio), y que esta relación no es debido al azar.
Residual standard error
Residual standard error El error estándar residual mide la calidad del ajuste del módelo, la cantidad promedio en el que la respuesta estimada del precio se desviará de la línea de regresión verdadera de los datos. En el modelo, el precio estimado puede desviarse de la línea de regresión verdadera en promedio 0.2285 en el la estimación del log(precio). Por otro lado este eror se calculó con 45,895 grados de libertad, para ello se tienen en cuenta los puntos que se usaron para estimar y los parámetros del modelo. En este caso se contaba con 45,904 puntos y nueve parámetros (intercepto y n_variables).
Multiple R-squared
Multiple R-squared Es una medida estadística que índica que tan bien se ajusta el modelo a los datos reales. En este caso el porcentaje de variación del precio que se explica por el modelo es del 82%, esto determina que el modelo está haciendo explicando de manera óptima.
F-statistic
F-statistic Es un indicador si existe relación entre los predictores y la variable respuesta. El p-valor menor que 0.05 indica que el modelo en general es significativo. Los grados de libertad en este caso se calculan nuevamente tomando los 9 parametros del modelo (n_variables e intercepto), y la cantidad de observaciones 45,904. Esto índica que el modelo rechaza la hipótesis nula que índica que un modelo con solo intercepto es igual a este modelo, es decir las variables aportan y el modelo actual es mejor a uno de solo el intercepto, demostrando significancia en el modelo obtenido.

Análisis residuos

  • El primer gráfico muestra un histográma de los residuos, donde se observa que tal como se esperaba los residuos tienen una distribución normal, donde el promedio de los mismos es un valor muy cercano a 0.
  • El segundo gráfico muestra los residuos vs los valores ajustados por el modelo, acá se podrían identificar patrones no lineales en los datos que los modelos no logran captar; sin embargo en este caso se presenta lo esperado, residuos distribuidos equitativamente al rededor de la linea horizontal, sin patrones, como una nube.
  • El tercer gráfico (QQplot) muestra si los residuos se distribuyen normalmente, esto se evidencia a través de la alineación con respecto a la recta; en este caso si bien no es perfectamente alineados a la diagonal principal, se evidenciar una tendencia sobre esta recta, algunas observaciones se encuentran mas alejadas de la recta, pero en general tienen un buen comportamiento.
  • El cuarto gráfico permite observar si los residuos se distribuyen por igual a lo largo del rango de la variable estimada, validando el supuesto de igual varianza (homocedasticidad). En este caso se observa una línea casi que horizontal, y muchos puntos con una dispersión muy similar, es decir distribuidos aleatoriamente, validando el supuesto de homocedasticidad.
  • El quinto gráfico evidencia la presencia de observaciones influyenes (en caso de existir), ya que no todos los valores atípicos influyen en el análisis de regresión. Los valores influyentes generan que al incluirlos u omitirlos del modelo se obtienen resultados diferentes. En este caso no hay puntos fuera de la distancia de Cook, por lo cual, se descarta la presencia de valores influyentes en el modelo.
properties_tratado <- properties %>%
  mutate(surface_patio  = surface_total - surface_covered ,
         log_price = log(price),
         log_rooms = log(rooms),
         log_bathrooms = log(bathrooms),
         log_surface_covered = log(surface_covered))  %>% 
  inner_join(.,mean_barrio, by = "l3") %>% mutate(Barrios = factor(Barrios))


properties_tratado <-  properties_tratado %>% select( -c(l3,  surface_total, price, rooms,
                                                          mean_price, bathrooms, surface_covered))

#Armamos el modelo
best_model <- lm(log_price ~  ., data = properties_tratado)

#Hist.
ggplot(best_model) + 
  geom_histogram(aes(.resid), colour = 'black', fill='tomato', bins=40)

plot(best_model)