Cargamos los datos e inspeccionamos brevemente las variables y sus tipos
# carga librerias tidyverse y ggplot2
suppressPackageStartupMessages(library(tidyverse))
suppressPackageStartupMessages(library(ggplot2))
#Cargamos datos y eliminamos columna id que no ayuda al analisis
ar_properties <- readRDS('ar_properties.rds') %>% select( -c('id') )
#Convertimos en factores las variables tipo chr
ar_properties <- ar_properties %>% mutate_if( is.character, as.factor )
#Inspeccionamos los datos
nrow(ar_properties)
[1] 45904
glimpse(ar_properties)
Observations: 45,904
Variables: 7
$ l3 [3m[38;5;246m<fct>[39m[23m Velez Sarsfield, Nuñez, Almagro, Almagro, Almagro, Almagro, Almagro, Almagro, Almagro, Almag...
$ rooms [3m[38;5;246m<dbl>[39m[23m 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2,...
$ bathrooms [3m[38;5;246m<dbl>[39m[23m 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1,...
$ surface_total [3m[38;5;246m<dbl>[39m[23m 95, 44, 40, 49, 40, 40, 40, 49, 40, 40, 40, 32, 40, 36, 90, 45, 54, 40, 33, 40, 40, 36, 38, ...
$ surface_covered [3m[38;5;246m<dbl>[39m[23m 69, 38, 37, 44, 37, 37, 37, 44, 37, 37, 37, 30, 34, 33, 90, 35, 48, 40, 32, 34, 36, 33, 34, ...
$ price [3m[38;5;246m<dbl>[39m[23m 199900, 147000, 92294, 115000, 77000, 88900, 88798, 110975, 92943, 99000, 96984, 125000, 995...
$ property_type [3m[38;5;246m<fct>[39m[23m Casa, Departamento, Departamento, Departamento, Departamento, Departamento, Departamento, De...
Observamos 5 variables del tipo numericas (rooms, bathrooms, surface_total, surface_covered y price), y 2 categoricas (property_type y l3)
# Calculamos el modelo
model <- lm(price~., data=ar_properties)
summary(model)
Call:
lm(formula = price ~ ., data = ar_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
Observaciones:
room es negativo (uno esperaria que a mayor cantidad de dambientes, mayor precio). Pero si interpretamos que esto es la variacion esperada de precios, manteniendo todas las demas variables constantes entonces interpretamos que para departamentos de igual tamaño, si se agrega un ambiente mas (achicando en promedio el tamaño de cada ambiente) el precio esperado bajaria.# Funcion para crear un caso de estudio
crear_caso <- function( barrio, rooms, bathrooms, surface_total, surface_covered, property_type )
{
new=ar_properties[FALSE,] %>% select( -c('price') )
new[1,] = list(barrio, rooms, bathrooms, surface_total, surface_covered, property_type)
return(new)
}
#Creamos los casos, y los 'etiquetamos'
casos <- do.call(rbind, list(
crear_caso(barrio='Abasto', rooms=3, bathrooms=2, surface_total=120, surface_covered=120, property_type='Departamento'),
crear_caso(barrio='Balvanera', rooms=2, bathrooms=3, surface_total=100, surface_covered=80, property_type='Departamento')
)) %>%
# creamos columna temporal para agrupar los casos
cbind(caso=c(1,2)) %>%
#agrupamos los casos
group_by(caso) %>% nest() %>%
#hacemos las predicciones para cada caso
mutate( prediction=map(data,function(data) data.frame(predict(model, data, se.fit=TRUE)))) %>%
unnest(data) %>% unnest(prediction) %>%
#descartamos la columna temporal de agrupacion
ungroup() %>% select(-'caso')
head(casos)
Observando las predicciones, podermos afirmar que segun el modelo el departamento mas grande (de Abasto) tendria considerablemente mas chances de ser el mas caro, aun teniendo el cuenta el desvio de la prediccion.
Se buscara a continuacion agrupar los barrios en 3 categorias de precio, dependiendo de su precio/m2 promedio. Al haber una mayor correlacion del precio con la superficie cubierta, utilizaremos a esta como referencia:
# calculamos el precio por metro cuadrado
mean_price_area <- ar_properties %>%
select( 'l3', 'price', 'surface_covered' ) %>%
mutate(precio_area=price/surface_covered) %>%
select(-c('price', 'surface_covered')) %>%
# y luego agrupamos por barrio, y calculamos la media
group_by( l3 ) %>%
summarise(mean_price_area=mean(precio_area))
# Calculamos los centroides de 3 categorias usando K-means
groups=kmeans(mean_price_area$mean_price_area, 3, centers=c(2000,2800,3500) )
# graficamos los puntos, junto con sus categorias
ggplot(mean_price_area, aes(x=mean_price_area, y='', color=as.factor(groups$cluster))) +
geom_jitter(width=0, height=0.5, size=2,alpha=0.8) +
coord_fixed(ratio=1000) +
theme(legend.position = "none") +
geom_vline(xintercept=2400, color = "blue") +
geom_vline(xintercept=3200, color = "blue")
# agregamos la columna de cuan caro es el barrio
mean_price_area$group <- groups$cluster
mean_price_area <- mean_price_area %>% arrange(mean_price_area)
Para realizar la particion en 3 grupos de precios, utilizamos el algoritmo k-means para encontrar los limites de los mismos. Realizando una inspeccion visual podemos observar un claro corte entre los mas caros y los del medio, y uno no tan claro (pero acceptable) entre los mas bajos y los medios. De aqui utilizamos estos limites encontrados para definir los precios altos, medios y bajos. Cabe tambien destacar que se forzo el valor inicial de los centroides del algoritmo k-means, ya que no todas las inicializacions aleatorias generaban resultados satisfactorios
ar_properties_range <- ar_properties %>%
inner_join( mean_price_area, by="l3" ) %>%
select( -'mean_price_area' )%>%
mutate(precio_barrio = case_when(group == 1 ~ 'bajo',
group == 2 ~ 'medio',
TRUE ~ 'alto')) %>%
select( -'l3', -'group' )
ar_properties_range$precio_barrio <- as.factor(ar_properties_range$precio_barrio)
glimpse(ar_properties_range)
Observations: 45,904
Variables: 7
$ rooms [3m[38;5;246m<dbl>[39m[23m 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2,...
$ bathrooms [3m[38;5;246m<dbl>[39m[23m 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1,...
$ surface_total [3m[38;5;246m<dbl>[39m[23m 95, 44, 40, 49, 40, 40, 40, 49, 40, 40, 40, 32, 40, 36, 90, 45, 54, 40, 33, 40, 40, 36, 38, ...
$ surface_covered [3m[38;5;246m<dbl>[39m[23m 69, 38, 37, 44, 37, 37, 37, 44, 37, 37, 37, 30, 34, 33, 90, 35, 48, 40, 32, 34, 36, 33, 34, ...
$ price [3m[38;5;246m<dbl>[39m[23m 199900, 147000, 92294, 115000, 77000, 88900, 88798, 110975, 92943, 99000, 96984, 125000, 995...
$ property_type [3m[38;5;246m<fct>[39m[23m Casa, Departamento, Departamento, Departamento, Departamento, Departamento, Departamento, De...
$ precio_barrio [3m[38;5;246m<fct>[39m[23m bajo, alto, medio, medio, medio, medio, medio, medio, medio, medio, medio, alto, alto, alto,...
Mediante la agrupacion de barrios por precio promedio del punto anterior, se procede a calcular el modelo lineal:
#funcion para ajustar el caso base
relevel.variable <- function(df, variable.name, new.base.level)
{
df[variable.name] <- relevel( df[[variable.name]], ref=new.base.level)
return(df)
}
# Calculamos el modelo utilizando solo el precio_barrio, en lugar del barrio actual
model <- lm( price~., data=ar_properties_range %>% relevel.variable('precio_barrio', 'medio'))
summary(model)
Call:
lm(formula = price ~ ., data = ar_properties_range %>% relevel.variable("precio_barrio",
"medio"))
Residuals:
Min 1Q Median 3Q Max
-438724 -36706 -4394 25242 689396
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -121842.62 2477.45 -49.18 <2e-16 ***
rooms -7452.96 466.69 -15.97 <2e-16 ***
bathrooms 36345.31 678.74 53.55 <2e-16 ***
surface_total 857.97 24.63 34.83 <2e-16 ***
surface_covered 1628.21 29.98 54.31 <2e-16 ***
property_typeDepartamento 103846.01 2263.16 45.88 <2e-16 ***
property_typePH 54991.30 2393.93 22.97 <2e-16 ***
precio_barrioalto 64692.14 723.90 89.37 <2e-16 ***
precio_barriobajo -29384.95 1046.44 -28.08 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 70720 on 45895 degrees of freedom
Multiple R-squared: 0.7474, Adjusted R-squared: 0.7474
F-statistic: 1.698e+04 on 8 and 45895 DF, p-value: < 2.2e-16
precio_barriobajo, y positivo para el otro coeficiente precio_barrioalto, y dejando el coeficiente de 0 (por omision) para precio_barriomedio (se forzo el caso baso a medio intencionalmente)Si nos atenemos estrictamente a los resultados numericos, el modelo de todos los barrios explica mejor la variabilidad cuando comparamos el R ajustado (utilizamos el R ajustado para comparar, ya que los modelos tienen distinta cantidad de variables, por lo cual se utiliza este mecanismo de compensacion para lgorar una comparacion mas ‘justa’). Aun asi el modelo de rango de precios parece ser mas simple y mas facilmente interpretable. Si la precision de la prediccion deseada lo permite, este 2do modelo simplificado podria ser una mejor opcion cuando no se necesita demasiada granularidad o presicion. Es necesario destacar que estos resultados varian dependiendo del corte de precio de los barrios que se realice, lo cual este modelo agrega un poco mas de arbitrareidad a la ecuacion.
Notando que la superficie cubierta y superficie total estan fuertemente correlacionadas, por lo que procedemos a crear una nueva variable a partir de estas:
# Obervamos si hay registros que tengan mas superficie cubierta que total (que seria imposible)
print(paste(
'Cantidad de registros con superficie total < superficie cubierta :',
nrow(ar_properties %>% filter(surface_total < surface_covered))
))
[1] "Cantidad de registros con superficie total < superficie cubierta : 0"
ar_properties_superficie_patio <-ar_properties_range %>% mutate(surface_patio=surface_total-surface_covered) %>% select(-'surface_total' )
glimpse(ar_properties_superficie_patio)
Observations: 45,904
Variables: 7
$ rooms [3m[38;5;246m<dbl>[39m[23m 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2,...
$ bathrooms [3m[38;5;246m<dbl>[39m[23m 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1,...
$ surface_covered [3m[38;5;246m<dbl>[39m[23m 69, 38, 37, 44, 37, 37, 37, 44, 37, 37, 37, 30, 34, 33, 90, 35, 48, 40, 32, 34, 36, 33, 34, ...
$ price [3m[38;5;246m<dbl>[39m[23m 199900, 147000, 92294, 115000, 77000, 88900, 88798, 110975, 92943, 99000, 96984, 125000, 995...
$ property_type [3m[38;5;246m<fct>[39m[23m Casa, Departamento, Departamento, Departamento, Departamento, Departamento, Departamento, De...
$ precio_barrio [3m[38;5;246m<fct>[39m[23m bajo, alto, medio, medio, medio, medio, medio, medio, medio, medio, medio, alto, alto, alto,...
$ surface_patio [3m[38;5;246m<dbl>[39m[23m 26, 6, 3, 5, 3, 3, 3, 5, 3, 3, 3, 2, 6, 3, 0, 10, 6, 0, 1, 6, 4, 3, 4, 3, 7, 0, 3, 0, 3, 5, ...
# Calculamos el modelo
model <- lm( price~., data=ar_properties_superficie_patio %>% relevel.variable( 'precio_barrio', 'medio' ))
summary(model)
Call:
lm(formula = price ~ ., data = ar_properties_superficie_patio %>%
relevel.variable("precio_barrio", "medio"))
Residuals:
Min 1Q Median 3Q Max
-438724 -36706 -4394 25242 689396
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -121842.62 2477.45 -49.18 <2e-16 ***
rooms -7452.96 466.69 -15.97 <2e-16 ***
bathrooms 36345.31 678.74 53.55 <2e-16 ***
surface_covered 2486.18 15.83 157.03 <2e-16 ***
property_typeDepartamento 103846.01 2263.16 45.88 <2e-16 ***
property_typePH 54991.30 2393.93 22.97 <2e-16 ***
precio_barrioalto 64692.14 723.90 89.37 <2e-16 ***
precio_barriobajo -29384.95 1046.44 -28.08 <2e-16 ***
surface_patio 857.97 24.63 34.83 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 70720 on 45895 degrees of freedom
Multiple R-squared: 0.7474, Adjusted R-squared: 0.7474
F-statistic: 1.698e+04 on 8 and 45895 DF, p-value: < 2.2e-16
Si comparamos los dos modelos, podemos apreciar que estos son identicos en cuanto a prediccion. El efecto final de aplicar una transformacion lineal entre variables tuvo como efecto el ajuste de los coeficientes, pero la predictivilidad sigue siendo exactamente la misma: mismo R2 ajustado, mismos residuos y mismos coeficientes con la excpecion descrita abajo.
Modelo original
surface_total 857.97 24.63 34.83 <2e-16 *** surface_covered 1628.21 29.98 54.31 <2e-16 ***
Modelo con transformacion lineal
surface_covered 2486.18 15.83 157.03 <2e-16 *** surface_patio 857.97 24.63 34.83 <2e-16 ***
donde podemos apreciar que el componente de precio generado por el par de variables arriba es el mismo que el de abajo, si consideramos que surface_patio = surface_total - surface_covered
Graficamos los residuos del modelo anterior:
ggplot(model, aes(.fitted, .resid)) +
geom_point(color = "lightcoral",alpha=0.2) +
geom_smooth() +
labs(x="precio estimado", y="Residuos", title='Residuos vs precio estimado')
ggplot(model, aes(sample=.resid)) +
stat_qq(color = "lightcoral") +
stat_qq_line()
Al analizar los residuos (y en especial la tendencia de estos) se puede observar que el modelo lineal no logra ajustar de forma que pueda explicar la tendencia observada. Tambein se puede observar que el modelo no es homocedastico, al aumentar la variabilidad mientras mas altos son los precios estimados. Tambien podemos observar en el q-q plot de los residuos que cuando estos son grandes se desvian de lo esperado para una distribucion normal
model <- lm( log(price)~log(rooms)+
log(bathrooms)+
log(surface_covered)+
surface_patio +
property_type +
precio_barrio
, data=ar_properties_superficie_patio)
summary(model)
Call:
lm(formula = log(price) ~ log(rooms) + log(bathrooms) + log(surface_covered) +
surface_patio + property_type + precio_barrio, data = ar_properties_superficie_patio)
Residuals:
Min 1Q Median 3Q Max
-1.33122 -0.14607 -0.00747 0.13441 1.34718
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 8.672e+00 1.865e-02 464.909 <2e-16 ***
log(rooms) -3.111e-02 3.775e-03 -8.241 <2e-16 ***
log(bathrooms) 1.800e-01 3.804e-03 47.319 <2e-16 ***
log(surface_covered) 8.089e-01 4.432e-03 182.507 <2e-16 ***
surface_patio 3.744e-03 7.938e-05 47.161 <2e-16 ***
property_typeDepartamento 2.479e-01 7.171e-03 34.564 <2e-16 ***
property_typePH 7.914e-02 7.619e-03 10.388 <2e-16 ***
precio_barriobajo -4.546e-01 3.405e-03 -133.514 <2e-16 ***
precio_barriomedio -2.664e-01 2.329e-03 -114.372 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2274 on 45895 degrees of freedom
Multiple R-squared: 0.822, Adjusted R-squared: 0.8219
F-statistic: 2.649e+04 on 8 and 45895 DF, p-value: < 2.2e-16
ggplot(model, aes(.fitted, .resid)) +
geom_point(color = "lightcoral",alpha=0.2) +
geom_smooth() +
labs(x="log(precio estimado)", y="Residuos", title='Residuos vs precio estimado')
ggplot(model, aes(sample=.resid)) +
stat_qq(color = "lightcoral") +
stat_qq_line()
Al analizar los resultados del modelo construido a partir del logaritmo de ciertas variables, podemos observar como este ajusta mejor que los casos anteriores, pudiendo explicar ~82% de la variabilidad del mismo, y al mismo tiempo mejorando el grafico de residuos: en este nuevo modelo pareceria haber una mejor homocedasticidad en un rango mas grande, y la distribucion de los residuos ajustan mejor a la distribucion normal.
suppressPackageStartupMessages(library(generics))
#analizamos las poblaciones
ar_properties_superficie_patio %>% count(property_type) %>% mutate(porcentage=n/nrow(ar_properties_superficie_patio))
#Calculamos el modelo lineal para las poblaciones discriminadas
modelos_por_tipo <- ar_properties_superficie_patio %>%
# agrupamos y anidamos
group_by(property_type) %>% nest() %>%
# calculamos el modelo lineal por tipo de propiedad, y descartamos los datos originales
mutate(lm=map(data,function(df) lm( price~., data=df))) %>% select( -'data' ) %>%
# Explayamos la columna de resumen del modelo
mutate(modeldata=map(lm, function(mod) glance(mod))) %>%
# explayamos la columna de detalles del modelo
mutate(tidy_lm=map(lm, function(lm) tidy(lm))) %>%
# descartamos la columna demodelo
select(-'lm')
# Imprimimos los detalles del modelo en general
modelos_por_tipo %>% unnest(modeldata) %>% select('property_type','adj.r.squared', 'df.residual', 'sigma')
# Imprimimos los detalles de los coeficientes
modelos_por_tipo %>% unnest(tidy_lm)
Cuando comparamos los distintos modelos generados cuando discriminamos por tipo de propiedad, comparando el R2 ajustado de cada uno, notamos que estos difieren considerablemente entre sí. Observamos que para departamentos, el modelo explica el 77% (recordamos que cuando no discriminabamos por tipo de propiedad el modelo explicaba el 74%); pero tambien notamos como para casa este valor es de tan solo 60%, y de 69% para PHs. De estos datos podemos estimar que los departamentos son mas predecibles para un modelo lineal, y al representar la gran mayoria de la poblacion total, la predictibilidad de esta poblacion aumentaba la predictibilidad del modelo combinado (respecto a predictibilidad de Casas y PHs por separado).
Aun asi, podemos extraer otras conclusiones al separar los modelos, como por ej, la variacion esperada de precio por metro cuadrado cubierto es distinta en los modelos, y con una gran significatividad en todos los casos (Siendo los departamentos los mas caros por metro cuadrado, seguido por los PHs y finalmente por las casas), dato que en el modelo combinado solo era representado como una diferencia “constante” que dependía solamente del tipo de propiedad.