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.
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)
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.
\[ 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\]
## 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.
\[ 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.
\[ 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.
\[ 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.
plot(rl_model)
\[ \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.
\[ 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.
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. |
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)