library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(kableExtra)
##
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
##
## group_rows
library(GGally)
## Loading required package: ggplot2
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
library(tidyverse)
## ── Attaching packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ tibble 3.0.3 ✓ purrr 0.3.4
## ✓ tidyr 1.1.2 ✓ stringr 1.4.0
## ✓ readr 1.4.0 ✓ forcats 0.5.0
## ── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x kableExtra::group_rows() masks dplyr::group_rows()
## x dplyr::lag() masks stats::lag()
library(tidymodels)
## ── Attaching packages ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidymodels 0.1.1 ──
## ✓ broom 0.7.1 ✓ recipes 0.1.14
## ✓ dials 0.0.9 ✓ rsample 0.0.8
## ✓ infer 0.5.3 ✓ tune 0.1.1
## ✓ modeldata 0.1.0 ✓ workflows 0.2.1
## ✓ parsnip 0.1.4 ✓ yardstick 0.0.7
## ── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidymodels_conflicts() ──
## x scales::discard() masks purrr::discard()
## x dplyr::filter() masks stats::filter()
## x recipes::fixed() masks stringr::fixed()
## x kableExtra::group_rows() masks dplyr::group_rows()
## x dplyr::lag() masks stats::lag()
## x yardstick::spec() masks readr::spec()
## x recipes::step() masks stats::step()
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
properties.train <- read.csv(file = './ar_properties_train.csv')
properties.test <- read.csv(file = './ar_properties_test.csv')
head(properties.train) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| id | l3 | rooms | bathrooms | surface_total | surface_covered | price | property_type |
|---|---|---|---|---|---|---|---|
| r22OfzZ3kXooSPoE5HMuZQ== | Almagro | 1 | 1 | 40 | 37 | 92294 | Departamento |
| atZQXVtyfG7+OiX6gYY3lA== | Almagro | 1 | 1 | 49 | 44 | 115000 | Departamento |
| Tur/v/qE41UBT83NM/bI7w== | Almagro | 1 | 1 | 40 | 37 | 88900 | Departamento |
| PNtNl6sWjHEyRPQAeRAIgw== | Almagro | 1 | 1 | 40 | 37 | 88798 | Departamento |
| Lhg4dNG9VmPbHt0Swy2ATA== | Almagro | 1 | 1 | 49 | 44 | 110975 | Departamento |
| oeLhuwomY2yj4A9TtDrgCA== | Almagro | 1 | 1 | 40 | 37 | 99000 | Departamento |
summary(properties.train)
## id l3 rooms bathrooms
## Length:32132 Length:32132 Min. :1.000 Min. :1.000
## Class :character Class :character 1st Qu.:2.000 1st Qu.:1.000
## Mode :character Mode :character Median :3.000 Median :1.000
## Mean :2.722 Mean :1.427
## 3rd Qu.:3.000 3rd Qu.:2.000
## Max. :8.000 Max. :5.000
## surface_total surface_covered price property_type
## Min. : 28 Min. : 26.00 Min. : 69500 Length:32132
## 1st Qu.: 46 1st Qu.: 42.00 1st Qu.:120000 Class :character
## Median : 65 Median : 58.00 Median :169000 Mode :character
## Mean : 80 Mean : 70.61 Mean :214991
## 3rd Qu.: 99 3rd Qu.: 85.00 3rd Qu.:260000
## Max. :320 Max. :265.00 Max. :950000
El data set cuenta con 8 variables por individuo:
id: Cadena de texto que identifica univocamente al individuol3: Variable categórica que representa el barrio. Si se observan los gráficos de frecuencia, se podrá ver que no todos los barrios están balanceados. Palermo es el barrio en donde hay más individuos, mientas que Catalinas en donde hay menos. Si se observa la tabla por frecuencias, se ve que de los 57 barrios presentes, los primeros 16 concentran más del 75% de los individuos del dataset.rooms: Entero que representa la cantidad de habitaciones de una propiedad. Los valores se encuentran entre 1 y 8, y cuyo valor medio esta en 3.bathrooms: Entero que representa la cantidad de baños que tiene una propiedad. Los valores se encuentran entre 1 y 5, el valor medio en 1.surface_total: Entero que representa la superficie total de una propiedad. Los valores se encuentran entre 28 y 320, el valor medio en 80.surface_covered: Entero que representa la superficie cubierta de una propiedad. Los valores se encuentran entre 28 y 265, el valor medio en 58.price: Entero que representa el precio de una propiedad. Los valores se encuentran entre 69500 y 9500000, el valor medio en 169000.property_type: Variable categórica que representa el tipo de una propiedad de una propiedad. Hay 3 tipos, Departamento, Ph y Casa, siendo Departamento el más frequente y Casa el menos frecuente.l3_freq <- as.data.frame(table(properties.train$l3)) %>%
arrange(desc(Freq))
l3_freq %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| Var1 | Freq |
|---|---|
| Palermo | 4890 |
| Belgrano | 2736 |
| Almagro | 2486 |
| Caballito | 2393 |
| Villa Crespo | 2095 |
| Recoleta | 1824 |
| Barrio Norte | 1359 |
| Villa Urquiza | 1319 |
| Flores | 916 |
| Nuñez | 887 |
| Balvanera | 883 |
| Villa Devoto | 527 |
| Colegiales | 523 |
| Villa del Parque | 500 |
| San Telmo | 488 |
| Saavedra | 433 |
| San Cristobal | 417 |
| Parque Centenario | 404 |
| Floresta | 366 |
| Puerto Madero | 357 |
| Boedo | 336 |
| Paternal | 327 |
| San Nicolás | 325 |
| Monserrat | 310 |
| Chacarita | 292 |
| Retiro | 291 |
| Villa Pueyrredón | 285 |
| Parque Chacabuco | 282 |
| Barracas | 280 |
| Villa Luro | 264 |
| Liniers | 260 |
| Mataderos | 259 |
| Once | 255 |
| Congreso | 246 |
| Coghlan | 240 |
| Las Cañitas | 187 |
| Abasto | 179 |
| Parque Patricios | 171 |
| Monte Castro | 168 |
| Constitución | 139 |
| Villa Santa Rita | 128 |
| Versalles | 113 |
| Villa Lugano | 113 |
| Villa Ortuzar | 109 |
| Centro / Microcentro | 105 |
| Boca | 104 |
| Villa General Mitre | 99 |
| Parque Avellaneda | 78 |
| Parque Chas | 78 |
| Pompeya | 65 |
| Velez Sarsfield | 56 |
| Villa Real | 55 |
| Tribunales | 54 |
| Agronomía | 51 |
| Villa Riachuelo | 13 |
| Villa Soldati | 9 |
| Catalinas | 3 |
barplot(table(properties.train$l3))
l3_freq_percentage <- data.frame(orden = c(), barrio = c(), porcentaje = c(), sumatoria = c())
for (i in 1:nrow(l3_freq)) {
percentage <- l3_freq$Freq[i] / nrow(properties.train) * 100
sum <- percentage
if (i > 1) {
sum <- sum + l3_freq_percentage$sumatoria[i - 1]
}
l3_freq_percentage <- rbind(
l3_freq_percentage,
data.frame(
orden = c(i),
barrio = c(l3_freq$Var1[i]),
porcentaje = c(percentage),
sumatoria = c(sum)
)
)
}
l3_freq_percentage$barrio <- l3_freq$Var1
l3_freq_percentage %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| orden | barrio | porcentaje | sumatoria |
|---|---|---|---|
| 1 | Palermo | 15.2184738 | 15.21847 |
| 2 | Belgrano | 8.5148761 | 23.73335 |
| 3 | Almagro | 7.7368356 | 31.47019 |
| 4 | Caballito | 7.4474045 | 38.91759 |
| 5 | Villa Crespo | 6.5199801 | 45.43757 |
| 6 | Recoleta | 5.6765841 | 51.11415 |
| 7 | Barrio Norte | 4.2294286 | 55.34358 |
| 8 | Villa Urquiza | 4.1049421 | 59.44852 |
| 9 | Flores | 2.8507407 | 62.29927 |
| 10 | Nuñez | 2.7604880 | 65.05975 |
| 11 | Balvanera | 2.7480393 | 67.80779 |
| 12 | Villa Devoto | 1.6401095 | 69.44790 |
| 13 | Colegiales | 1.6276609 | 71.07556 |
| 14 | Villa del Parque | 1.5560812 | 72.63164 |
| 15 | San Telmo | 1.5187352 | 74.15038 |
| 16 | Saavedra | 1.3475663 | 75.49795 |
| 17 | San Cristobal | 1.2977717 | 76.79572 |
| 18 | Parque Centenario | 1.2573136 | 78.05303 |
| 19 | Floresta | 1.1390514 | 79.19208 |
| 20 | Puerto Madero | 1.1110420 | 80.30312 |
| 21 | Boedo | 1.0456865 | 81.34881 |
| 22 | Paternal | 1.0176771 | 82.36649 |
| 23 | San Nicolás | 1.0114528 | 83.37794 |
| 24 | Monserrat | 0.9647703 | 84.34271 |
| 25 | Chacarita | 0.9087514 | 85.25146 |
| 26 | Retiro | 0.9056392 | 86.15710 |
| 27 | Villa Pueyrredón | 0.8869663 | 87.04407 |
| 28 | Parque Chacabuco | 0.8776298 | 87.92170 |
| 29 | Barracas | 0.8714055 | 88.79310 |
| 30 | Villa Luro | 0.8216109 | 89.61471 |
| 31 | Liniers | 0.8091622 | 90.42388 |
| 32 | Mataderos | 0.8060500 | 91.22993 |
| 33 | Once | 0.7936014 | 92.02353 |
| 34 | Congreso | 0.7655919 | 92.78912 |
| 35 | Coghlan | 0.7469190 | 93.53604 |
| 36 | Las Cañitas | 0.5819744 | 94.11801 |
| 37 | Abasto | 0.5570771 | 94.67509 |
| 38 | Parque Patricios | 0.5321798 | 95.20727 |
| 39 | Monte Castro | 0.5228433 | 95.73011 |
| 40 | Constitución | 0.4325906 | 96.16270 |
| 41 | Villa Santa Rita | 0.3983568 | 96.56106 |
| 42 | Versalles | 0.3516743 | 96.91273 |
| 43 | Villa Lugano | 0.3516743 | 97.26441 |
| 44 | Villa Ortuzar | 0.3392257 | 97.60363 |
| 45 | Centro / Microcentro | 0.3267770 | 97.93041 |
| 46 | Boca | 0.3236649 | 98.25408 |
| 47 | Villa General Mitre | 0.3081041 | 98.56218 |
| 48 | Parque Avellaneda | 0.2427487 | 98.80493 |
| 49 | Parque Chas | 0.2427487 | 99.04768 |
| 50 | Pompeya | 0.2022906 | 99.24997 |
| 51 | Velez Sarsfield | 0.1742811 | 99.42425 |
| 52 | Villa Real | 0.1711689 | 99.59542 |
| 53 | Tribunales | 0.1680568 | 99.76348 |
| 54 | Agronomía | 0.1587203 | 99.92220 |
| 55 | Villa Riachuelo | 0.0404581 | 99.96265 |
| 56 | Villa Soldati | 0.0280095 | 99.99066 |
| 57 | Catalinas | 0.0093365 | 100.00000 |
boxplot(properties.train$rooms, properties.train$bathrooms, names = c('rooms', 'bathrooms'))
boxplot(properties.train$surface_total, properties.train$surface_covered, names = c('surface_total', 'surface_covered'))
boxplot(properties.train$price, names = c('price'))
table(properties.train$property_type) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| Var1 | Freq |
|---|---|
| Casa | 809 |
| Departamento | 28203 |
| PH | 3120 |
barplot(table(properties.train$property_type))
ggpairs(
data = properties.train %>%
select(
rooms,
bathrooms,
surface_total,
surface_covered,
price
),
upper = list(continuous = ggally_cor_v1_5)
)
Utilizando el dataset de training:
a. Crear un modelo para predecir el precio con todas las covariables.
modelo_lm.todos <- lm(price ~ l3 + rooms + bathrooms + surface_total + surface_covered + property_type, data = properties.train)
tidy(modelo_lm.todos, conf.int = TRUE)
## # A tibble: 63 x 7
## term estimate std.error statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) -109144. 5784. -18.9 5.28e-79 -120480. -97808.
## 2 l3Agronomía 1241. 10652. 0.117 9.07e- 1 -19638. 22120.
## 3 l3Almagro -3480. 5182. -0.672 5.02e- 1 -13636. 6676.
## 4 l3Balvanera -25835. 5491. -4.70 2.55e- 6 -36598. -15072.
## 5 l3Barracas -7974. 6412. -1.24 2.14e- 1 -20542. 4594.
## 6 l3Barrio Norte 51694. 5325. 9.71 3.03e-22 41255. 62132.
## 7 l3Belgrano 71926. 5170. 13.9 7.26e-44 61792. 82060.
## 8 l3Boca -47781. 8258. -5.79 7.28e- 9 -63968. -31595.
## 9 l3Boedo -19759. 6203. -3.19 1.45e- 3 -31917. -7600.
## 10 l3Caballito 6354. 5189. 1.22 2.21e- 1 -3817. 16525.
## # … with 53 more rows
b. Analizar los resultados del modelo:
Significado de los coeficientes estimados:
-109143.7839 es el precio neto esperado para una propiedad sin cuartos (rooms=0), sin baños (bathrooms=0), sin superficie total (surface_total=0), sin superficie cubierta (surface_covered=0) que es de un tipo Casa (property_*=0 representa el property_type=Casa) y que esta en el barrio Abasto (l3*=0 representa l3=Abasto). Dicho de una manera más sencilla, este valor representa el precio que tendrá una Casa por el solo hecho de estar en el barrio del Abasto.rooms se interpreta como el incremento en el precio de una propiedad por aumentar un cuarto (manteniendo el resto de las variables constantes). Ya que dicho coeficiente tiene un valor negativo (-4359.7289) indica una disminución, particularmente, cada incremento en la cantidad de cuartos resultará en una disminución de 4359.7289 en el precio de la propiedad.bathrooms se interpreta como el incremento en el precio de una propiedad por aumentar un baño (manteniendo el resto de las variables constantes). Particularmente, cada incremento en la cantidad de bañor resultará en un aumento de 34367.2123 en el precio de la propiedad.surface_total se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie total (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie total resultará en un aumento de 890.5585 en el precio de la propiedad.surface_covered se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie cubierta (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie cubierta resultará en un aumento de 1497.9310 en el precio de la propiedad.l3*) representan la diferencia entre ese grupo en particular y el barrio del Abasto. Por ejemplo, l3Agronomía cuyo valor es 1241.0966 quiere decir que al mantener todas las otras variables constantes una propiedad en el barrio de Agronomía tendrá un precio 1241.0966 unidades mayor que en el barrio del Abasto.property*) representan la diferencia entre ese grupo en particular y el tipo de propiedad Casa. Por ejemplo, property_typeDepartamento cuyo valor es 91485.7410 quiere decir que al mantener todas las otras variables constantes una propiedad del tipo Departamento tendrá un precio 91485.7410 unidades mayor que una propiedad del tipo Casa.tidy(modelo_lm.todos, conf.int = TRUE) %>%
select(term, statistic, p.value, conf.low, conf.high) %>%
arrange(p.value)
## # A tibble: 63 x 5
## term statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 l3Puerto Madero 41.6 0. 244026. 268144.
## 2 bathrooms 44.7 0. 32862. 35873.
## 3 surface_covered 43.6 0. 1431. 1565.
## 4 property_typeDepartamento 34.4 1.35e-254 86272. 96700.
## 5 surface_total 31.5 3.84e-215 835. 946.
## 6 (Intercept) -18.9 5.28e- 79 -120480. -97808.
## 7 property_typePH 16.8 5.06e- 63 40826. 51615.
## 8 l3Belgrano 13.9 7.26e- 44 61792. 82060.
## 9 l3Palermo 13.2 1.30e- 39 57214. 77189.
## 10 l3Las Cañitas 13.1 2.24e- 39 78440. 105927.
## # … with 53 more rows
En este modelo se observa que mientras las variables bathrooms, sufrace_covered, surface_total, property_type y rooms resultan estadísticamente significativas para explicar el precio de la propiedad (p-valores < 0.05), no pasa con todas las categorías de l3, hay algunas que resultan significativas y otras no.
ggplotly(
ggplot(
tidy(modelo_lm.todos, conf.int = TRUE),
aes(estimate, term, xmin = conf.low, xmax = conf.high, height = 0)
) +
geom_point(color = "forestgreen", size=2) +
geom_vline(xintercept = 0, lty = 4, color = "black") +
geom_errorbarh(color = "forestgreen", size=1) +
theme_bw() +
labs(y = "Coeficientes β", x = "Estimación"),
height = 800
)
En el anterior gráfico se puede observar los coeficientes estimados para el modelo con sus respectivos intervalos de confianza. En él se puede apreciar que el intervalo de confianza (IC) del 95% de las variables surface_total, surface_covered, rooms, bathrooms y todas las dummies de property_type no contienen al cero, es decir, resultan estadisticamente significativas para explicar el precio de la propiedad. Los intervalos de confianza de algunas de las variables dummies de l3 sí contienen al cero, por lo que no se puede asegurar que todos los valores de dicha variable sean estadisticamente significativos para explicar el precio de la propiedad.
broom::glance(modelo_lm.todos)
## # A tibble: 1 x 12
## r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.777 0.777 66933. 1803. 0 62 -4.03e5 8.05e5 8.06e5
## # … with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
c. Realizar un modelo sin la covariable l3 e interpretar sus resultados (todas las partes de la salida que consideren relevantes).
modelo_lm.noL3 <- lm(price ~ rooms + bathrooms + surface_total + surface_covered + property_type, data = properties.train)
tidy(modelo_lm.noL3, conf.int = TRUE)
## # A tibble: 7 x 7
## term estimate std.error statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) -128676. 3333. -38.6 1.07e-318 -135210. -122143.
## 2 rooms -13657. 617. -22.1 8.68e-108 -14867. -12448.
## 3 bathrooms 42564. 899. 47.3 0. 40801. 44327.
## 4 surface_total 856. 33.0 25.9 1.40e-146 791. 920.
## 5 surface_covered 1819. 40.0 45.5 0. 1740. 1897.
## 6 property_typeDepart… 133033. 3049. 43.6 0. 127056. 139010.
## 7 property_typePH 66457. 3233. 20.6 2.59e- 93 60121. 72793.
En este modelo se observa que todas las variables resultan estadísticamente significativas para explicar el precio de la propiedad (p-valores < 0.05). Hay que resaltar que ningún intervalo de confianza contiene al 0.
Significado de los coeficientes estimados:
-128676.4483 es el precio neto esperado para una propiedad sin cuartos (rooms=0), sin baños (bathrooms=0), sin superficie total (surface_total=0), sin superficie cubierta (surface_covered=0) y que es de un tipo Casa (property_*=0 representa el property_type=Casa). Dicho de una manera más sencilla, este valor representa el precio que tendrá una Casa.rooms se interpreta como el incremento en el precio de una propiedad por aumentar un cuarto (manteniendo el resto de las variables constantes). Ya que dicho coeficiente tiene un valor negativo (-13657.4480) indica una disminución, particularmente, cada incremento en la cantidad de cuartos resultará en una disminución de 13657.4480 en el precio de la propiedad.bathrooms se interpreta como el incremento en el precio de una propiedad por aumentar un baño (manteniendo el resto de las variables constantes). Particularmente, cada incremento en la cantidad de bañor resultará en un aumento de 42564.0592 en el precio de la propiedad.surface_total se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie total (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie total resultará en un aumento de 855.5727 en el precio de la propiedad.surface_covered se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie cubierta (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie cubierta resultará en un aumento de 1818.6596 en el precio de la propiedad.property*) representan la diferencia entre ese grupo en particular y el tipo de propiedad Casa. Por ejemplo, property_typeDepartamento cuyo valor es 133033.0341 quiere decir que al mantener todas las otras variables constantes una propiedad del tipo Departamento tendrá un precio 133033.0341 unidades mayor que una propiedad del tipo Casa.d. ¿Cuál es el modelo que mejor explica la variabilidad del precio?
broom::glance(modelo_lm.noL3)
## # A tibble: 1 x 12
## r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.686 0.686 79419. 11674. 0 6 -4.08e5 8.16e5 8.16e5
## # … with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
Como hay distinta cantidad de variables en los modelos se debe utilizar el \(R^2_a\). En este caso se podría decir que el mejor modelo es el que utiliza todas las covariables ya que su \(R^2_a\) es mayor (0.7766239) que el del modelo que no utiliza l3 (0.6855061).
a. En el ejercicio anterior deberían haber encontrado que algunos barrios son significativos, aunque no todos. Crear una nueva variable barrios que permita agrupar a los barrios. Explicar el análisis exploratorio para definir la nueva variable y los criterios utilizados en la construcción de la misma.
Se creará una variable agrupando barrios por el metro cuadrado promedio.
barrios.sup <- properties.train %>%
mutate(price_sup = price / surface_total) %>%
group_by(l3) %>%
summarize(price_sup = mean(price_sup)) %>%
arrange(-price_sup)
## `summarise()` ungrouping output (override with `.groups` argument)
barrios.sup %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| l3 | price_sup |
|---|---|
| Puerto Madero | 5438.285 |
| Las Cañitas | 3514.309 |
| Palermo | 3351.408 |
| Belgrano | 3316.252 |
| Recoleta | 3282.091 |
| Nuñez | 3225.282 |
| Barrio Norte | 3213.048 |
| Retiro | 2970.304 |
| Colegiales | 2858.154 |
| Coghlan | 2835.364 |
| Villa Urquiza | 2815.417 |
| Saavedra | 2620.620 |
| Caballito | 2609.084 |
| Villa Ortuzar | 2588.543 |
| Chacarita | 2587.910 |
| Abasto | 2553.281 |
| Villa Crespo | 2536.028 |
| Almagro | 2468.381 |
| Parque Centenario | 2463.233 |
| San Telmo | 2430.877 |
| Villa Devoto | 2422.252 |
| Villa Pueyrredón | 2385.928 |
| Parque Chas | 2363.225 |
| Villa del Parque | 2316.323 |
| Centro / Microcentro | 2307.064 |
| Barracas | 2283.309 |
| San Nicolás | 2245.270 |
| Villa Luro | 2233.816 |
| Tribunales | 2205.028 |
| Paternal | 2204.351 |
| Monte Castro | 2180.769 |
| Flores | 2163.566 |
| Boedo | 2150.451 |
| Balvanera | 2144.486 |
| Villa General Mitre | 2138.195 |
| Once | 2137.558 |
| Villa Real | 2134.709 |
| Villa Santa Rita | 2134.319 |
| Monserrat | 2121.919 |
| Catalinas | 2103.326 |
| Congreso | 2098.626 |
| Liniers | 2090.877 |
| San Cristobal | 2090.678 |
| Agronomía | 2009.210 |
| Parque Chacabuco | 1980.307 |
| Versalles | 1967.438 |
| Parque Patricios | 1946.075 |
| Floresta | 1880.990 |
| Mataderos | 1876.505 |
| Velez Sarsfield | 1842.675 |
| Constitución | 1786.940 |
| Boca | 1781.651 |
| Parque Avellaneda | 1733.703 |
| Villa Riachuelo | 1637.033 |
| Villa Lugano | 1425.710 |
| Pompeya | 1339.678 |
| Villa Soldati | 1239.104 |
summary(barrios.sup$price_sup)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1239 2091 2205 2365 2588 5438
quantile(barrios.sup$price_sup, c(0, 1/3, 2/3, 1)) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| x | |
|---|---|
| 0% | 1239.104 |
| 33.33333% | 2130.186 |
| 66.66667% | 2441.663 |
| 100% | 5438.285 |
Los grupos creando serán tres: - precio_bajo cuando promedio del precio sobre superficie total sea menor o igual a 2130.186 - precio_medio cuando el promedio del precio sobre superficie total sea mayor a 2130.186 y menor o igual a 2441.663 - precio_alto cuando el promedio del precio sobre superficie total sea mayor a 2441.663.
barrios.sup.map <- barrios.sup %>%
mutate(map = case_when(
price_sup <= 2130.186 ~ 'precio_bajo',
price_sup <= 2441.663 ~ 'precio_medio',
TRUE ~ 'precio_alto'
))
barrios.sup.map %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| l3 | price_sup | map |
|---|---|---|
| Puerto Madero | 5438.285 | precio_alto |
| Las Cañitas | 3514.309 | precio_alto |
| Palermo | 3351.408 | precio_alto |
| Belgrano | 3316.252 | precio_alto |
| Recoleta | 3282.091 | precio_alto |
| Nuñez | 3225.282 | precio_alto |
| Barrio Norte | 3213.048 | precio_alto |
| Retiro | 2970.304 | precio_alto |
| Colegiales | 2858.154 | precio_alto |
| Coghlan | 2835.364 | precio_alto |
| Villa Urquiza | 2815.417 | precio_alto |
| Saavedra | 2620.620 | precio_alto |
| Caballito | 2609.084 | precio_alto |
| Villa Ortuzar | 2588.543 | precio_alto |
| Chacarita | 2587.910 | precio_alto |
| Abasto | 2553.281 | precio_alto |
| Villa Crespo | 2536.028 | precio_alto |
| Almagro | 2468.381 | precio_alto |
| Parque Centenario | 2463.233 | precio_alto |
| San Telmo | 2430.877 | precio_medio |
| Villa Devoto | 2422.252 | precio_medio |
| Villa Pueyrredón | 2385.928 | precio_medio |
| Parque Chas | 2363.225 | precio_medio |
| Villa del Parque | 2316.323 | precio_medio |
| Centro / Microcentro | 2307.064 | precio_medio |
| Barracas | 2283.309 | precio_medio |
| San Nicolás | 2245.270 | precio_medio |
| Villa Luro | 2233.816 | precio_medio |
| Tribunales | 2205.028 | precio_medio |
| Paternal | 2204.351 | precio_medio |
| Monte Castro | 2180.769 | precio_medio |
| Flores | 2163.566 | precio_medio |
| Boedo | 2150.451 | precio_medio |
| Balvanera | 2144.486 | precio_medio |
| Villa General Mitre | 2138.195 | precio_medio |
| Once | 2137.558 | precio_medio |
| Villa Real | 2134.709 | precio_medio |
| Villa Santa Rita | 2134.319 | precio_medio |
| Monserrat | 2121.919 | precio_bajo |
| Catalinas | 2103.326 | precio_bajo |
| Congreso | 2098.626 | precio_bajo |
| Liniers | 2090.877 | precio_bajo |
| San Cristobal | 2090.678 | precio_bajo |
| Agronomía | 2009.210 | precio_bajo |
| Parque Chacabuco | 1980.307 | precio_bajo |
| Versalles | 1967.438 | precio_bajo |
| Parque Patricios | 1946.075 | precio_bajo |
| Floresta | 1880.990 | precio_bajo |
| Mataderos | 1876.505 | precio_bajo |
| Velez Sarsfield | 1842.675 | precio_bajo |
| Constitución | 1786.940 | precio_bajo |
| Boca | 1781.651 | precio_bajo |
| Parque Avellaneda | 1733.703 | precio_bajo |
| Villa Riachuelo | 1637.033 | precio_bajo |
| Villa Lugano | 1425.710 | precio_bajo |
| Pompeya | 1339.678 | precio_bajo |
| Villa Soldati | 1239.104 | precio_bajo |
properties.train.barrios <- merge(properties.train, barrios.sup.map, by = 'l3') %>%
rename(barrios = map)
head(properties.train.barrios) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| l3 | id | rooms | bathrooms | surface_total | surface_covered | price | property_type | price_sup | barrios |
|---|---|---|---|---|---|---|---|---|---|
| Abasto | 8c0orLjaWrwN5NYYZ9oCYQ== | 3 | 1 | 81 | 75 | 184000 | Departamento | 2553.281 | precio_alto |
| Abasto | Ka1KIE3+G5Ca36dVZuat4w== | 4 | 2 | 77 | 73 | 235000 | Departamento | 2553.281 | precio_alto |
| Abasto | JdQovtBqRtnAGa9UbuzXbw== | 5 | 2 | 145 | 104 | 330000 | Departamento | 2553.281 | precio_alto |
| Abasto | i5Ll4GEXKs40b36b3honww== | 1 | 1 | 28 | 28 | 99800 | Departamento | 2553.281 | precio_alto |
| Abasto | opYtEK0kxXcMU4WvYy/jfg== | 1 | 1 | 54 | 42 | 128000 | Departamento | 2553.281 | precio_alto |
| Abasto | W+B7/p1CZdoyXJKreB3WHw== | 4 | 2 | 77 | 73 | 235000 | Departamento | 2553.281 | precio_alto |
b. Calcular el modelo que predice el precio en función de las nuevas covariables e interpretar sus resultados (todas las partes de la salida que consideren relevantes).
modelo_lm.barrios <- lm(price ~ rooms + bathrooms + surface_total + surface_covered + property_type + barrios, data = properties.train.barrios)
tidy(modelo_lm.barrios, conf.int = TRUE)
## # A tibble: 9 x 7
## term estimate std.error statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) -81384. 3242. -25.1 1.03e-137 -87738. -75029.
## 2 rooms -11511. 584. -19.7 6.48e- 86 -12656. -10365.
## 3 bathrooms 37024. 855. 43.3 0. 35349. 38700.
## 4 surface_total 911. 31.2 29.2 1.29e-184 849. 972.
## 5 surface_covered 1719. 37.8 45.5 0. 1645. 1793.
## 6 property_typeDepart… 104944. 2918. 36.0 1.14e-277 99224. 110664.
## 7 property_typePH 53361. 3063. 17.4 1.17e- 67 47357. 59365.
## 8 barriosprecio_bajo -71262. 1484. -48.0 0. -74171. -68353.
## 9 barriosprecio_medio -52439. 1103. -47.5 0. -54601. -50278.
En este modelo se observa que todas las variables resultan estadísticamente significativas para explicar el precio de la propiedad (p-valores < 0.05). Hay que resaltar que ningún intervalo de confianza contiene al 0.
Significado de los coeficientes estimados:
-81383.5092 es el precio neto esperado para una propiedad sin cuartos (rooms=0), sin baños (bathrooms=0), sin superficie total (surface_total=0), sin superficie cubierta (surface_covered=0), que es de un tipo Casa (property_*=0 representa el property_type=Casa) y que es de un barrio de precio alto (barrios*=0 representa el barrios=precio_alto). Dicho de una manera más sencilla, este valor representa el precio que tendrá una Casa de un barrio de precio alto.rooms se interpreta como el incremento en el precio de una propiedad por aumentar un cuarto (manteniendo el resto de las variables constantes). Ya que dicho coeficiente tiene un valor negativo (-11510.5181) indica una disminución, particularmente, cada incremento en la cantidad de cuartos resultará en una disminución de 11510.5181 en el precio de la propiedad.bathrooms se interpreta como el incremento en el precio de una propiedad por aumentar un baño (manteniendo el resto de las variables constantes). Particularmente, cada incremento en la cantidad de bañor resultará en un aumento de 37024.3838 en el precio de la propiedad.surface_total se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie total (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie total resultará en un aumento de 910.6953 en el precio de la propiedad.surface_covered se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie cubierta (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie cubierta resultará en un aumento de 1719.1450 en el precio de la propiedad.property*) representan la diferencia entre ese grupo en particular y el tipo de propiedad Casa. Por ejemplo, property_typeDepartamento cuyo valor es 104943.6217 quiere decir que al mantener todas las otras variables constantes una propiedad del tipo Departamento tendrá un precio 104943.6217 unidades mayor que una propiedad del tipo Casa.barrios*) representan la diferencia entre ese grupo en particular y el barrio de precio alto. Por ejemplo, barriosprecio_bajo cuyo valor es -71261.8968 quiere decir que al mantener todas las otras variables constantes una propiedad del barrio de precio bajo tendrá un precio 71261.8968 unidades menor que una propiedad de un barrio de precio alto.c. ¿Qué modelo explica mejor la variabilidad de los datos, el que utiliza la variable l3 o el que utiliza barrio? En su opinión, ¿Qué modelo es más útil? ¿Porqué?
broom::glance(modelo_lm.barrios)
## # A tibble: 1 x 12
## r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.719 0.719 75071. 10278. 0 8 -4.06e5 8.13e5 8.13e5
## # … with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
Como hay distinta cantidad de variables en los modelos se debe utilizar el \(R^2_a\). En este caso se podría decir que el mejor modelo es el que utiliza todas las covariables ya que su \(R^2_a\) es mayor (0.7766239) que el resto de los modelos (0.6855061 para el modelo sin l3 y 0.7190024 para el modelo de barrios).
d. La interpretación de los coeficientes de las variables surface_covered y surface_total puede ser un poco problemática ya que se encuentran altamente correlacionadas. Entonces, podemos construir una nueva variable sup_descubierta para la diferencia entre ambas superficies. Calcular nuevamente el modelo lineal del punto 3.b) (modelo con variable barrio) para todas las covariables previas (excepto surface_total), incluyendo surface_covered y sup_descubierta e interpretar los coeficientes de estas dos últimas variables.
properties.train.sup_descubierta <- properties.train.barrios %>%
mutate(sup_descubierta = surface_total - surface_covered)
head(properties.train.sup_descubierta) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped"))
| l3 | id | rooms | bathrooms | surface_total | surface_covered | price | property_type | price_sup | barrios | sup_descubierta |
|---|---|---|---|---|---|---|---|---|---|---|
| Abasto | 8c0orLjaWrwN5NYYZ9oCYQ== | 3 | 1 | 81 | 75 | 184000 | Departamento | 2553.281 | precio_alto | 6 |
| Abasto | Ka1KIE3+G5Ca36dVZuat4w== | 4 | 2 | 77 | 73 | 235000 | Departamento | 2553.281 | precio_alto | 4 |
| Abasto | JdQovtBqRtnAGa9UbuzXbw== | 5 | 2 | 145 | 104 | 330000 | Departamento | 2553.281 | precio_alto | 41 |
| Abasto | i5Ll4GEXKs40b36b3honww== | 1 | 1 | 28 | 28 | 99800 | Departamento | 2553.281 | precio_alto | 0 |
| Abasto | opYtEK0kxXcMU4WvYy/jfg== | 1 | 1 | 54 | 42 | 128000 | Departamento | 2553.281 | precio_alto | 12 |
| Abasto | W+B7/p1CZdoyXJKreB3WHw== | 4 | 2 | 77 | 73 | 235000 | Departamento | 2553.281 | precio_alto | 4 |
modelo_lm.sup_descubierta <- lm(price ~ rooms + bathrooms + surface_covered + sup_descubierta + property_type + barrios, data = properties.train.sup_descubierta)
tidy(modelo_lm.sup_descubierta, conf.int = TRUE)
## # A tibble: 9 x 7
## term estimate std.error statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) -81384. 3242. -25.1 1.03e-137 -87738. -75029.
## 2 rooms -11511. 584. -19.7 6.48e- 86 -12656. -10365.
## 3 bathrooms 37024. 855. 43.3 0. 35349. 38700.
## 4 surface_covered 2630. 19.8 133. 0. 2591. 2669.
## 5 sup_descubierta 911. 31.2 29.2 1.29e-184 849. 972.
## 6 property_typeDepart… 104944. 2918. 36.0 1.14e-277 99224. 110664.
## 7 property_typePH 53361. 3063. 17.4 1.17e- 67 47357. 59365.
## 8 barriosprecio_bajo -71262. 1484. -48.0 0. -74171. -68353.
## 9 barriosprecio_medio -52439. 1103. -47.5 0. -54601. -50278.
En este modelo se observa que todas las variables resultan estadísticamente significativas para explicar el precio de la propiedad (p-valores < 0.05). Hay que resaltar que ningún intervalo de confianza contiene al 0.
Significado de los coeficientes estimados: - El coeficiente estimado surface_covered se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie cubierta (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie cubierta resultará en un aumento de 2629.8403 en el precio de la propiedad. - El coeficiente estimado sup_descubierta se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie descubierta (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie descubierta resultará en un aumento de 910.6953 en el precio de la propiedad.
broom::glance(modelo_lm.sup_descubierta)
## # A tibble: 1 x 12
## r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.719 0.719 75071. 10278. 0 8 -4.06e5 8.13e5 8.13e5
## # … with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
Este modelo tiene el mismo \(R^2\) que el modelo de barrios anterior, así que, se podría decir que explican una variabilidad muy similar.
Analizar los residuos del modelo elaborado en el punto 3.d) y evaluar el cumplimiento de los supuestos del modelo lineal.
plot(modelo_lm.sup_descubierta)
broom::augment(modelo_lm.sup_descubierta) %>%
arrange(-.hat) %>%
head()
## # A tibble: 6 x 13
## price rooms bathrooms surface_covered sup_descubierta property_type barrios
## <int> <int> <int> <int> <int> <chr> <chr>
## 1 649000 8 5 153 0 Casa precio…
## 2 185000 4 1 260 0 Casa precio…
## 3 169000 4 1 250 0 Casa precio…
## 4 390000 4 5 250 70 Casa precio…
## 5 475000 3 4 251 0 Casa precio…
## 6 335000 2 2 220 15 Casa precio…
## # … with 6 more variables: .fitted <dbl>, .resid <dbl>, .std.resid <dbl>,
## # .hat <dbl>, .sigma <dbl>, .cooksd <dbl>
.hat > 0.075). El mayor es 0.003302447.Diagnóstico del modelo: El modelo creado no cumple con los supuestos del modelo lineal. Parecen existir problemas de heterocedasticidad (varianza no constante) y falta de normalidad.
Crear un modelo para log(price) e interpretar los parámetros estimados de este nuevo modelo. Comparar la performance del modelo de 3.d) con éste, tanto en términos de la variabilidad explicada como del cumplimiento de los supuestos del modelo lineal:
\(log(price) = \beta_0 + \beta_1 log(rooms) + \beta_2 log(bathrooms) + \beta_3 log(surface_covered) + \beta_4 property\_type + \beta_5 barrio + \beta_6 surface\_patio\)
modelo_lm.log <- lm(log(price) ~ log(rooms) + log(bathrooms) + log(surface_covered) + property_type + barrios + sup_descubierta , data = properties.train.sup_descubierta)
tidy(modelo_lm.log, conf.int = TRUE)
## # A tibble: 9 x 7
## term estimate std.error statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) 8.42 0.0239 352. 0. 8.38 8.47
## 2 log(rooms) -0.0782 0.00485 -16.1 2.81e- 58 -0.0877 -0.0687
## 3 log(bathrooms) 0.183 0.00493 37.2 2.52e-297 0.174 0.193
## 4 log(surface_covered) 0.859 0.00570 151. 0. 0.848 0.871
## 5 property_typeDepart… 0.238 0.00947 25.1 6.51e-138 0.219 0.256
## 6 property_typePH 0.0635 0.00998 6.37 1.95e- 10 0.0440 0.0831
## 7 barriosprecio_bajo -0.367 0.00489 -75.1 0. -0.377 -0.358
## 8 barriosprecio_medio -0.245 0.00363 -67.6 0. -0.253 -0.238
## 9 sup_descubierta 0.00405 0.000103 39.3 0. 0.00385 0.00425
En este modelo se observa que todas las variables resultan estadísticamente significativas para explicar el precio de la propiedad (p-valores < 0.05). Hay que resaltar que ningún intervalo de confianza contiene al 0.
Significado de los coeficientes estimados:
8.4220639240 es el precio neto (en escala logaritmica) esperado para una propiedad con un cuarto (log(rooms) = 0 cuando rooms = 1), con un baño (log(bathrooms) = 0 cuando bathrooms = 1), con una superficie cubierta de 1 (log(surface_covered) = 0 cuando surface_covered = 1), que es de un tipo Casa (property_*=0 representa el property_type=Casa), que es de un barrio de precio alto (barrios*=0 representa el barrios=precio_alto) y sin superficie descubierta (sup_descubierta = 0).rooms es que el precio dimunuye 7.8219677 % por cada cuarto.bathrooms es que el precio aumenta 18.3464679 % por cada baño.surface_covered es que el precio aumenta 85.9334996 % por cada aumento en la unidad de la superficie cubierta.property*) representan la diferencia entre ese grupo en particular y el tipo de propiedad Casa. Por ejemplo, property_typeDepartamento cuyo valor es 0.237812090 quiere decir que al mantener todas las otras variables constantes una propiedad del tipo Departamento tendrá un precio 0.237812090 unidades mayor (en escala logaritmica) que una propiedad del tipo Casa.barrios*) representan la diferencia entre ese grupo en particular y el barrio de precio alto. Por ejemplo, barriosprecio_bajo cuyo valor es -0.367118913 quiere decir que al mantener todas las otras variables constantes una propiedad del barrio de precio bajo tendrá un precio 0.367118913 unidades menor (en escala logaritmica) que una propiedad de un barrio de precio alto.sup_descubierta se interpreta como el incremento en el precio de una propiedad por aumentar en una unidad la superficie descubierta (manteniendo el resto de las variables constantes). Particularmente, cada incremento en una unidad en la superficie descubierta resultará en un aumento de 910.6953 en el precio de la propiedad.broom::glance(modelo_lm.log)
## # A tibble: 1 x 12
## r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.791 0.791 0.247 15218. 0 8 -668. 1356. 1440.
## # … with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
Como este modelo tiene la misma cantidad de variables que el del punto 3.d, se puede usar el valor de \(R^2\) para comparar la variabilidad explicada entre ellos. El \(R^2\) del modelo log(price) es mayor que el del otro modelo (0.7912287 contra 0.7190723), así que, se puede decir que el modelo log(price) explica una mayor variabilidad.
plot(modelo_lm.log)
broom::augment(modelo_lm.log) %>%
arrange(-.hat) %>%
head()
## # A tibble: 6 x 12
## `log(price)` `log(rooms)` `log(bathrooms)` `log(surface_co… property_type
## <dbl> <dbl> <dbl> <dbl> <chr>
## 1 12.9 0 0 5.19 Casa
## 2 12.9 0 0 5.19 Casa
## 3 12.3 0 1.10 5.01 Casa
## 4 11.7 0 0 5.16 PH
## 5 12.5 1.39 0 4.79 Casa
## 6 12.3 1.39 0 4.79 Casa
## # … with 7 more variables: barrios <chr>, sup_descubierta <int>, .fitted <dbl>,
## # .std.resid <dbl>, .hat <dbl>, .sigma <dbl>, .cooksd <dbl>
.hat > 0.075). El mayor es 0.002534460.Diagnóstico del modelo: El modelo creado no cumple con los supuestos del modelo lineal. Parecen existir problemas de heterocedasticidad (varianza no constante) y falta de normalidad.
Se generan dos modelos. El primero definiendo la variable dependiente, price, en forma logaritmica, mientras el resto de las covariables en forma lineal (se utilizarán las variables rooms, bathrooms, surface_covered, property_type, barrios y sup_descubierta).
modelo_lm.1 <- lm(log(price) ~ rooms + bathrooms + surface_covered + property_type + barrios + sup_descubierta , data = properties.train.sup_descubierta)
tidy(modelo_lm.1, conf.int = TRUE)
## # A tibble: 9 x 7
## term estimate std.error statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) 11.0 0.0120 922. 0. 11.0 11.1
## 2 rooms 0.0429 0.00216 19.9 1.84e- 87 0.0387 0.0471
## 3 bathrooms 0.123 0.00316 39.0 0. 0.117 0.129
## 4 surface_covered 0.00797 0.0000730 109. 0. 0.00782 0.00811
## 5 property_typeDepart… 0.283 0.0108 26.3 1.32e-150 0.262 0.304
## 6 property_typePH 0.130 0.0113 11.5 2.36e- 30 0.107 0.152
## 7 barriosprecio_bajo -0.372 0.00548 -67.9 0. -0.383 -0.361
## 8 barriosprecio_medio -0.250 0.00407 -61.4 0. -0.258 -0.242
## 9 sup_descubierta 0.00473 0.000115 41.0 0. 0.00450 0.00496
broom::glance(modelo_lm.1)
## # A tibble: 1 x 12
## r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.737 0.737 0.277 11261. 0 8 -4369. 8758. 8841.
## # … with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
El segundo definiendo a la variable dependiente en forma lineal mientras que algunas de las independientes (rooms, sufrace_covered) en forma logaritmica.
modelo_lm.2 <- lm(price ~ log(rooms) + log(surface_covered) + property_type + barrios, data = properties.train.sup_descubierta)
tidy(modelo_lm.2, conf.int = TRUE)
## # A tibble: 7 x 7
## term estimate std.error statistic p.value conf.low conf.high
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) -920195. 6871. -134. 0. -933663. -906727.
## 2 log(rooms) -58581. 1576. -37.2 4.64e-296 -61670. -55491.
## 3 log(surface_covered) 276807. 1578. 175. 0. 273713. 279900.
## 4 property_typeDepart… 70709. 3020. 23.4 2.92e-120 64790. 76627.
## 5 property_typePH 15676. 3234. 4.85 1.26e- 6 9337. 22015.
## 6 barriosprecio_bajo -76155. 1581. -48.2 0. -79253. -73056.
## 7 barriosprecio_medio -56193. 1176. -47.8 0. -58499. -53888.
broom::glance(modelo_lm.2)
## # A tibble: 1 x 12
## r.squared adj.r.squared sigma statistic p.value df logLik AIC BIC
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.678 0.678 80316. 11296. 0 6 -4.08e5 8.17e5 8.17e5
## # … with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
De los 5 modelos ya realizados, se eligirá los que expliquen la mayor variabilidad, es decir, el modelo de log(price) y el de todas las covariables.
modelos <- list(
modelo_lm.todos = modelo_lm.todos,
modelo_lm.noL3 = modelo_lm.noL3,
modelo_lm.barrios = modelo_lm.barrios,
modelo_lm.sup_descubierta = modelo_lm.sup_descubierta,
modelo_lm.log = modelo_lm.log
)
map_df(modelos, broom::glance, .id = "model") %>%
arrange(desc(adj.r.squared))
## # A tibble: 5 x 13
## model r.squared adj.r.squared sigma statistic p.value df logLik AIC
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 mode… 0.791 0.791 2.47e-1 15218. 0 8 -6.68e2 1.36e3
## 2 mode… 0.777 0.777 6.69e+4 1803. 0 62 -4.03e5 8.05e5
## 3 mode… 0.719 0.719 7.51e+4 10278. 0 8 -4.06e5 8.13e5
## 4 mode… 0.719 0.719 7.51e+4 10278. 0 8 -4.06e5 8.13e5
## 5 mode… 0.686 0.686 7.94e+4 11674. 0 6 -4.08e5 8.16e5
## # … with 4 more variables: BIC <dbl>, deviance <dbl>, df.residual <int>,
## # nobs <int>
Evalue estos 4 (cuatro) modelos en términos de su capacidad predictiva en el dataset de training, fundamentando claramente su elección con la/s métrica/s que considere adecuada/s.
Como se va a utilizar un modelo para predecir nuevos datos nos interesa observar el error de los modelos en ambos datasets: training y testing. Una métrica para medir el error de predicción es RMSE (error cuadrático medio o root mean square error en inglés). Hay que resaltar que el valor de esta métrica está en las mismas unidades que los datos originales.
\(RMSE = \sqrt{\frac{\sum(\hat{y_i}-y_i)^2}{n}}\)
Hay que tener en cuenta que dos de los modelos tienen como variable dependiente log(price) y no price. Así que, se deberá transformar el .fitted para que refleje el price.
modelos_evaluar <- list(
modelo_lm.todos = modelo_lm.todos,
modelo_lm.log = modelo_lm.log,
modelo_lm.1 = modelo_lm.1,
modelo_lm.2 = modelo_lm.2
)
predicciones_training <- map(.x = modelos_evaluar, .f = augment)
predicciones_training$modelo_lm.log$.fitted = exp(predicciones_training$modelo_lm.log$.fitted)
predicciones_training$modelo_lm.1$.fitted = exp(predicciones_training$modelo_lm.1$.fitted)
map_dfr(
.x = predicciones_training,
.f = rmse,
truth = properties.train$price,
estimate = .fitted,
.id = "modelo"
) %>%
arrange(.estimate)
## # A tibble: 4 x 4
## modelo .metric .estimator .estimate
## <chr> <chr> <chr> <dbl>
## 1 modelo_lm.todos rmse standard 66867.
## 2 modelo_lm.2 rmse standard 183567.
## 3 modelo_lm.log rmse standard 184529.
## 4 modelo_lm.1 rmse standard 198955.
Predecir los valores de precios de las propiedades en el dataset de testing (recuerden que deben realizar las mismas transformaciones que hicieron en el set de training) y comparar la performance de los modelos seleccionados con la/s métrica/s elegidas previamente. Determinar con cuál modelo se queda y por qué.
properties.test.sup_descubierta <- merge(properties.test, barrios.sup.map, by = 'l3') %>%
rename(barrios = map) %>%
mutate(sup_descubierta = surface_total - surface_covered)
predicciones_testing = map(.x = modelos_evaluar, .f = augment, newdata = properties.test.sup_descubierta)
predicciones_testing$modelo_lm.log$.fitted = exp(predicciones_testing$modelo_lm.log$.fitted)
predicciones_testing$modelo_lm.1$.fitted = exp(predicciones_testing$modelo_lm.1$.fitted)
map_dfr(
.x = predicciones_testing,
.f = rmse,
truth = price,
estimate = .fitted,
.id="modelo"
) %>%
arrange(.estimate)
## # A tibble: 4 x 4
## modelo .metric .estimator .estimate
## <chr> <chr> <chr> <dbl>
## 1 modelo_lm.todos rmse standard 65805.
## 2 modelo_lm.log rmse standard 71810.
## 3 modelo_lm.2 rmse standard 79718.
## 4 modelo_lm.1 rmse standard 87227.