El objetivo del presente trabajo es analizar los precios de las viviendas en el Partido de San Isidro con el fin deteminar las condicionantes que lo modifican.
Este trabajo utiliza los datos de Properati. Los datos fueron descargados el día 19/06/2020
¿Qué contienen los datos descargados?
datos_properati <- read.csv("ar_properties.csv",
encoding = "UTF-8",
stringsAsFactors = FALSE)
names(datos_properati)
## [1] "id" "ad_type" "start_date" "end_date"
## [5] "created_on" "lat" "lon" "l1"
## [9] "l2" "l3" "l4" "l5"
## [13] "l6" "rooms" "bedrooms" "bathrooms"
## [17] "surface_total" "surface_covered" "price" "currency"
## [21] "price_period" "title" "description" "property_type"
## [25] "operation_type"
Se observa en el dataset que la variable l3 hace referencia a los partidos. A partir de ella, se seleccionan los datos del Partido de San Isidro.
prop_si <- datos_properati %>%
filter(l3 == "San Isidro")
En el dataset original hay observaciones sin partido. ¿Alguna pertenece a San Isidro? Para esto se utiliza la información en el título y en la descripción
sin_partido <- datos_properati %>%
filter(l3 == "" & l2 == "Bs.As. G.B.A. Zona Norte")
grep("isidro", sin_partido$title)
## integer(0)
grep("isidro", sin_partido$description)
## integer(0)
Dado que ni en el título ni en la descripción se encuentra la palabra “isidro”, se puede estimar que de las 2949 observaciones sin partido en la Zona Norte del Gran Buenos Aires, ninguna de ellas pertenecería a San Isidro.
¿Cuantos días pasaron entre en la primer públicación y la última?
max(ymd(prop_si$created_on)) - min(ymd(prop_si$created_on))
## Time difference of 389 days
¿Cómo se distribuye en el tiempo los avisos publicados?
prop_si %>%
mutate(created_on = ymd(created_on),
year = year(created_on),
month = month(created_on),
mes = case_when(
month <10 ~ paste0("0", month),
TRUE ~ as.character(month)) ,
periodo = paste0(year, mes)) %>%
ggplot() +
geom_bar(aes(x= (periodo)), color= "black") +
labs(title = "Cantidad de avisos publicados en San Isidro",
subtitle = "Alquiler y Venta",
x = "Periodo",
y = "Cantidad de avisos",
caption = "Fuente: Properati") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
¿Cuáles fueron los 5 días con más publicaciones de avisos?
prop_si %>%
mutate(fecha = ymd(created_on)) %>%
group_by(fecha) %>%
summarise(cantidad = n()) %>%
arrange(desc(cantidad)) %>%
top_n(5) %>%
mutate(dia = weekdays(fecha)) %>%
select(fecha, dia, cantidad) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = T,
position = "left")
## Selecting by cantidad
| fecha | dia | cantidad |
|---|---|---|
| 2019-05-31 | viernes | 270 |
| 2019-08-13 | martes | 186 |
| 2019-10-12 | sábado | 178 |
| 2019-05-30 | jueves | 157 |
| 2019-12-05 | jueves | 153 |
¿Qué tipo de operaciones se realizaron y en qué moneda?
prop_si %>%
group_by(operation_type, currency) %>%
summarise(cantidad = n()) %>%
rename(Transaccion = operation_type) %>%
spread(currency,
value = cantidad) %>%
rename(`Sin Especificar` = V1) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = T,
position = "left")
| Transaccion | Sin Especificar | ARS | USD |
|---|---|---|---|
| Alquiler | 95 | 5060 | 1067 |
| Alquiler temporal | 10 | 431 | 370 |
| Venta | 114 | 40 | 9321 |
¿Cuáles son los tipos de propiedades que se comercializaron?
prop_si %>%
group_by(operation_type, property_type) %>%
summarise(cantidad = n()) %>%
rename(Transaccion = operation_type) %>%
spread(property_type,
value = cantidad) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = T,
position = "left")
| Transaccion | Casa | Casa de campo | Cochera | Departamento | Depósito | Local comercial | Lote | Oficina | Otro | PH |
|---|---|---|---|---|---|---|---|---|---|---|
| Alquiler | 1765 | NA | 51 | 2400 | 92 | 672 | 23 | 777 | 75 | 367 |
| Alquiler temporal | 690 | NA | NA | 105 | NA | 1 | NA | 3 | 1 | 11 |
| Venta | 4299 | 3 | 170 | 2952 | 60 | 397 | 661 | 287 | 96 | 550 |
A los efectos de evaluar como se construye el precio de la vivienda, solo se tendrán en cuanta los datos de venta en USD de inmuebles con destino residencial.
Considerando que posteriormente la localización geográfica será utilizada, también se filtran las observaciones que no tienen coordenadas geográficas. Se convierten las variables a sf.
prop_si_geo <- prop_si %>%
filter(operation_type == "Venta", currency == "USD",
property_type %in% c("Casa", "Casa de campo", "Departamento", "PH"),
!is.na(lat) & !is.na(lon)) %>%
st_as_sf(coords = c("lon", "lat"), crs = 4326)
Se verifica que todas las propiedades se encuentren en el partido.
limites_si <- getbb("Partido de San Isidro, Buenos Aires", format_out = "sf_polygon")
pal <- colorFactor(c("#8dd3c7", "#ffffb3", "#bebada", "#fb8072"),
domain = c("Casa", "Casa de campo", "Departamento", "PH"))
leaflet() %>%
addTiles() %>%
addPolygons(data= limites_si, fillOpacity = .3, color = "black", stroke = FALSE) %>%
addCircleMarkers(data = prop_si_geo,
color = ~pal(property_type),
stroke = FALSE,
popup = paste("Tipo", prop_si_geo$property_type, "<br>",
"Precio:", prop_si_geo$price, " USD", "<br>",
"M2 cubiertos:", prop_si_geo$surface_covered, "<br>",
"Publicado el:", prop_si_geo$created_on)
)
Algunas propiedades se encontrarían por fuera del partido. A continuación se muestra un mapa estatíco que refleja de manera más evidente esta situación.
ggplot() +
geom_sf(data = limites_si, alpha = 0.5 ) +
geom_sf(data = prop_si_geo) +
labs(title = "Propiedades residenciales en venta",
subtitle = paste0("Propiedades publicadas entre: ",
min(ymd(prop_si$created_on)), " y ", max(ymd(prop_si$created_on))),
caption= "Fuente: Properati 2020",
y="",
x="") +
theme_void()
Efectivamente hay propiedades fuera del partido. Se genera una variable para las parcelas dentro_si para detectar las parcelas que se encuentran dentro de los límites del partido.
prop_si_geo <- prop_si_geo %>%
mutate(dentro_si = st_intersects(prop_si_geo, limites_si, sparse = FALSE)) %>%
filter(dentro_si == TRUE) %>%
select(-dentro_si)
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
ggplot() +
geom_sf(data = limites_si, alpha = 0.5 ) +
geom_sf(data = prop_si_geo) +
labs(title = "Propiedades residenciales en venta",
subtitle = paste0("Propiedades publicadas entre: ",
min(ymd(prop_si$created_on)), " y ", max(ymd(prop_si$created_on))),
caption= "Fuente: Properati 2020",
y="",
x="") +
theme_void()
¿Cómo se distribuyen los precios de estos inmuebles?
prop_si_geo %>%
ggplot() +
geom_boxplot(aes(x = property_type, y = price)) +
labs(title = "Distribución del precio de la vivieda",
y = "Precio (USD)",
x= "Tipo de propiedad",
caption = "Fuente: Properati 2020") +
scale_y_continuous(labels = comma) +
theme_minimal()
En primer lugar, se realiza una regresión simple explicando el precio de la vivienda (price) según su superficie total (surface_total)
prop_si_geo %>%
ggplot() +
geom_point(aes(x = surface_total, y = price)) +
labs(title = "Relación entre superficie y precio",
y = "Precio (USD)",
x= "Superficie Total",
caption = "Fuente: Properati") +
scale_y_continuous(labels = comma) +
theme_minimal()
## Warning: Removed 946 rows containing missing values (geom_point).
regresion1 <- lm(price ~ surface_total, prop_si_geo)
export_summs(regresion1)
| Model 1 | |
|---|---|
| (Intercept) | 364815.03 *** |
| (7599.64) | |
| surface_total | 233.02 *** |
| (10.65) | |
| N | 4042 |
| R2 | 0.11 |
| *** p < 0.001; ** p < 0.01; * p < 0.05. | |
Como vemos, el R2 es muy bajo: se explican muy pocos precios.
A fin de optimizar el modelo, se incorporan variables:
price)rooms), la cantitad de dormitorios (bedrooms), la cantidad de baños (bathrooms), la superficie cubierta (surface_covered), la superficie total (surface_total) y el tipo de propiedad (property_type).regresion2 <- lm(price ~ rooms + bedrooms + bathrooms + surface_covered + surface_total + property_type,
prop_si_geo)
export_summs(regresion2)
| Model 1 | |
|---|---|
| (Intercept) | -62413.52 * |
| (30188.62) | |
| rooms | 31788.53 ** |
| (10316.25) | |
| bedrooms | -7810.65 |
| (13832.51) | |
| bathrooms | 135647.37 *** |
| (9028.52) | |
| surface_covered | 370.84 *** |
| (35.71) | |
| surface_total | 14.53 |
| (8.00) | |
| property_typeDepartamento | 5208.76 |
| (19118.55) | |
| property_typePH | -81765.81 *** |
| (23476.79) | |
| N | 1668 |
| R2 | 0.42 |
| *** p < 0.001; ** p < 0.01; * p < 0.05. | |
El resumen de la regresión también se podría visualizar con la función summary().
summary(regresion2)
##
## Call:
## lm(formula = price ~ rooms + bedrooms + bathrooms + surface_covered +
## surface_total + property_type, data = prop_si_geo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2838265 -82093 -11344 52560 5512993
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -62413.516 30188.624 -2.067 0.038846
## rooms 31788.530 10316.249 3.081 0.002094
## bedrooms -7810.647 13832.508 -0.565 0.572382
## bathrooms 135647.372 9028.522 15.024 < 0.0000000000000002
## surface_covered 370.843 35.706 10.386 < 0.0000000000000002
## surface_total 14.533 7.999 1.817 0.069436
## property_typeDepartamento 5208.762 19118.549 0.272 0.785313
## property_typePH -81765.807 23476.789 -3.483 0.000509
##
## (Intercept) *
## rooms **
## bedrooms
## bathrooms ***
## surface_covered ***
## surface_total .
## property_typeDepartamento
## property_typePH ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 277200 on 1660 degrees of freedom
## (3320 observations deleted due to missingness)
## Multiple R-squared: 0.4202, Adjusted R-squared: 0.4178
## F-statistic: 171.9 on 7 and 1660 DF, p-value: < 0.00000000000000022
Con esta segunda regresión, el R2 aumenta considerablemente en relación a la primer regresión. Sin embargo, sigue siendo bajo. Al incorporar la zonificación, ¿se podría ajustar mejor el modelo?
Michael Manville, Paavo Monkkonen y Michael Lens, postulan en su artículo It’s Time to End Single-Family Zoning que no deberia existir la zonificación donde solo se permita la vivienda unifamiliar (R1 en Estados Unidos). Esta zonificación genera aumento de precio, exclusión, segregación, y no se aprovecha la infraestructura de la ciudad.
En este sentido, ¿cómo está zonificado el suelo en San Isidro? Según el Plano de Zonificación del Partido y el Código de Ordenamiento Urbano, se observa una predominancia de usos residenciales.
Plano de zonificación
Se redibuja el plano de zonificación del partido de San Isidro y se asignan los colores.
ggplot() +
geom_sf(data = zonificacion, aes(fill= ZONA)) +
scale_fill_manual(values = c(
"APP1" = "gray71",
"APP2" = "gray71",
"AR" = "grey87",
"Ca1" = "salmon",
"Cb1" = "salmon",
"Cb2" = "salmon",
"CE1" = "rosybrown1",
"Cm1" = "salmon",
"Cm2" = "salmon",
"Cm3" = "salmon",
"Cm4" = "salmon",
"Cm5" = "salmon",
"Cma1" = "salmon",
"Cma2" = "salmon",
"Cma3" = "salmon",
"Cma4" = "salmon",
"Cmb1" = "salmon",
"Cmb3" = "salmon",
"CmbB" = "salmon",
"CR1" = "sandybrown",
"DUP1" = "grey87",
"E" = "seagreen",
"EC" = "palegreen1" ,
"EH" = "honeydew1",
"EPR" = "honeydew1",
"ES" = "lightskyblue",
"ID" = "plum2",
"IE" = "plum2",
"IN" = "plum2",
"Ra1" = "khaki3",
"Ra2" = "khaki3",
"Ra3" = "khaki3",
"Rb1" = "lightgoldenrodyellow",
"Rb2" = "lightgoldenrodyellow",
"Rb3" = "lightgoldenrodyellow",
"Rb4" = "lightgoldenrodyellow",
"RbPN" = "lightgoldenrodyellow",
"Rm1" = "khaki1",
"Rm2" = "khaki1",
"Rm3" = "khaki1",
"Rm4" = "khaki1",
"Rma" = "khaki1",
"Rma1" = "khaki3",
"Rma2" = "khaki3",
"Rma3" = "khaki3",
"Rma4" = "khaki3",
"Rma5" = "khaki3",
"Rmb1" = "khaki1",
"Rmb2" = "khaki1",
"Rmb3" = "khaki1",
"Rmb4" = "khaki1",
"Rmb5" = "khaki1",
"RmbB" = "khaki1",
"Ru" = "grey87",
"S" = "lightblue"
)) +
theme_void() +
theme(legend.position = "none")
Todas las zonas del partido permiten el uso de vivienda unifamiliar (como uso predominante o como uso complementario). Esto no ocurre para la vivienda multifamiliar. El uso vivienda multifamiliar es conforme en las siguientes zonas según el cuadro de Usos: Cm2, Ca1, APP2, Rm2, Rma2, Ra1, Ra2, Ra3, Ca1, Cma2, Rm4, Rma1, Rma2, Rma3, Rma5, Cma1, Cma3, Cma4
zonificacion <- zonificacion %>%
mutate(superficie = st_area(zonificacion),
permite_multi = ifelse(ZONA %in% c("Cm2", "Ca1", "APP2", "Rm2", "Rma2", "Ra1", "Ra2", "Ra3", "Ca1", "Cma2", "Rm4", "Rma1", "Rma2", "Rma3", "Rma5", "Cma1", "Cma3", "Cma4" ), "si", "no"),
zona = ZONA) %>%
select(zona, superficie, permite_multi)
zonificacion %>%
mutate(sup_ha = as.numeric(superficie) / 10000) %>%
st_set_geometry(NULL) %>%
ggplot() +
geom_bar(aes(x = zona, weight = sup_ha, fill = permite_multi)) +
labs(title = "Superficie según zona",
fill = "¿Permite Multifamiliar?",
y = "Superfice (ha)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
¿Cómo quedaría entonces la comparación entre superficie disponible para vivienda multifamiliar, y superficie para vivienda unifamiliar?
zonificacion %>%
mutate(sup_ha = as.numeric(superficie) / 10000) %>%
st_set_geometry(NULL) %>%
ggplot() +
geom_bar(aes(x = permite_multi, weight = sup_ha, fill = permite_multi)) +
labs(title = "Superficie según la posibilidad de construir un edificio multifamiliar",
fill = "¿Permite Multifamiliar?",
y = "Superfice (ha)",
x = "") +
theme_minimal()
Es importante aclarar que las superficies en ambos casos incluyen el espacio público (calle, vereda, etc). El objetivo es tener un panorama general.
Entonces, en el partido de San Isidro hay poca superficie donde se permite la vivienda multifamiliar.
¿En que zonas se ubican las propiedades analizadas?
ggplot() +
geom_sf(data = prop_si_geo) +
geom_sf(data = zonificacion, aes(fill= permite_multi), alpha = 0.5) +
geom_sf(data = limites_si, fill = NA, alpha = 0.5 ) +
labs(title = "Mapa de Zonificación de San Isidro y propiedades en venta",
fill = "¿Permite Multifamiliar?",
caption= "Fuente: Properati 2020") +
theme_void()
Se observa en el mapa una mayor extensión de zonas donde no se permite vivienda multifamiliar.
¿Hay alguna concentración de propiedades en venta? ¿Dónde se ubican los hotspots?
bbox <- getbb('Partido de San Isidro, Buenos Aires')
map_si <- get_stamenmap(bbox, zoom = 12, maptype = 'terrain')
ggmap(map_si)+
stat_density2d(data = prop_si_geo %>% cbind(., st_coordinates(prop_si_geo)),
aes(x = X, y = Y, fill = ..density..),
geom = 'tile', contour = limites_si, alpha = 0.5) +
geom_sf(data = zonificacion %>% filter(permite_multi == "si"),
aes(color = permite_multi),
fill = NA, alpha = 0.5, inherit.aes = FALSE) +
scale_color_manual(values = "grey") +
geom_sf(data = limites_si, fill = NA, alpha = 0.5, size = 2, inherit.aes = FALSE) +
labs(title = "Concentración de propiedades en venta",
caption= "Fuente: Properati 2020",
color = "Zonas de multifamiliar",
fill = "Densidad") +
scale_fill_viridis_c(option = "A") +
theme_void()
Hay una concentración de propiedades en venta principalmente en zonas donde se permiten las viviendas multifamilias, en particular en la zona del centro de Martinez-Acassuso y del centro de San Isidro.
Se incorpora la zona correspondiente a cada propiedad a fin de incluir la zonificación en el estudio de regresión.
prop_si_geo_zona <- st_join(prop_si_geo, zonificacion) %>%
select(-superficie)
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
Se regresan los datos tomando la variable binaria permite_multi (que toma los valores si o no). Y se consideran solo los valores de superficie cubierta, cantidad de ambientes, tipo de propiedad, y si se encuentra en una zona de multifamiliar.
regresion3 <- lm(price ~
rooms + surface_covered + property_type + permite_multi, prop_si_geo_zona)
export_summs(regresion3)
| Model 1 | |
|---|---|
| (Intercept) | 2285.85 |
| (18223.81) | |
| rooms | 55756.71 *** |
| (3751.66) | |
| surface_covered | 1048.05 *** |
| (32.62) | |
| property_typeDepartamento | 21165.14 |
| (14092.63) | |
| property_typePH | -96147.08 *** |
| (18699.10) | |
| permite_multisi | -5738.91 |
| (13292.64) | |
| N | 3618 |
| R2 | 0.44 |
| *** p < 0.001; ** p < 0.01; * p < 0.05. | |
confint(regresion3)
## 2.5 % 97.5 %
## (Intercept) -33444.131 38015.835
## rooms 48401.137 63112.284
## surface_covered 984.084 1112.012
## property_typeDepartamento -6465.160 48795.449
## property_typePH -132808.933 -59485.230
## permite_multisi -31800.740 20322.926
Si bien el R2 aumenta en relación a la regresión 2, aún no es suficiente para determinar como se comporta el precio de las viviendas en San Isidro.
Para resumir, el valor hedónico de los precios de las viviendas se encuentra afectado por distintas variables, de los cuales es importante destacar la superficie y la cantidad de ambientes. La zonificación no parecería incidir de manera significativa en los precios. Con el objetivo de profundizar el presente análisis, sería conveniente incorporar la metodología aplicada por A. Stewart Fotheringham, Chris Brunsdon, Martin Charlton en “Geographically Weighted Regression: The Analysis of Spatially Varying Relationships (2002)” para estudiar el precio de la vivienda en Londres, a fin de evaluar la dependecia espacial.