Para vender algo innecesario, primero debe comprar algo innecesario, pero no tenemos dinero.
- Tres de Prostokvashino
Introducción
Dio la casualidad de que vivo en mi departamento (o condominio local) en Montreal. Y una vez, hace aproximadamente un año, me visitó la idea de que sería bueno mudarse a su propia casa. Ya tenía algo de experiencia en la compra y venta de viviendas, y, en principio, sería posible abordar este problema simplemente, como lo hacen la mayoría de los residentes locales: contratar a un agente de bienes raíces y dejar que se ocupe de todos los problemas, pero sería aburrido y poco interesante.
Por lo tanto, decidí abordar este asunto científicamente. Hay una tarea: debes averiguar cuánto vale lo que tengo y dónde puedo pagarlo. Bueno, una pregunta pasajera: entender dónde sopla el viento. Y explorar los cálculos geo-espacial en el R .
En principio, estaba claro de inmediato que no sacaría solo una casa familiar separada (localmente) si quisiera quedarme en un área civilizada y golpear el calentamiento global con un paseo diario en bicicleta. Otra opción local común es comprar dúplex o triplex, es decir. casas donde hay dos o tres apartamentos: vives en uno,en el resto crías conejosel resto se entrega a los residentes. Luego aparece otra cantidad desconocida: ingresos por alquiler.
Por lo tanto, quería hacer un mapa de la ciudad con los precios de la vivienda en venta, los precios de alquiler y también poder rastrear cómo todo esto cambia con el tiempo.
zillow, , , , , , : https://apciq.ca/en/real-estate-market/. , , .
, , , , , , : https://github.com/Froren/realtorca
— , , - requests beatifulsoap, .
— , , , , , ; , .
, openstreet map, .
— , , sqlite , , . , , , , ..
R, tidy-verse, Simple Features for R, — - Geocomputation with R, ggplot2 ( tidyverse), tmap.
, , (join?) .
, , dplyr , :
R , :
library(tidyverse)
library(sf)
property<-read_csv("....") %>%
st_as_sf(coords=c("lng","lat"), crs=4326) %>%
st_transform(crs=32188)
:
neighbourhood<-geojson_sf("quartierreferencehabitation.geojson") %>%
st_transform(32188) %>%
filter(nom_qr %in% c("Saint-Louis", "Milton-Parc")) %>%
summarize() %>%
st_buffer(dist=0)
:
neighbors <- st_join(property, neighbourhood, left=F)
openstreetmap :
osm_neighbourhood<-read_osm(st_bbox(neighbourhood%>%st_transform(4326)), ext=1.5, type="esri")
tmap :
library(tmap)
library(tmaptools)
tm_shape(osm_neighbourhood) + tm_rgb(alpha=0.7)+
tm_shape(neighbourhood) + tm_borders(col='red',alpha=0.8) +
tm_shape(neighbors) + tm_symbols(shape=3,size=0.2,alpha=0.8) +
tm_shape(ref_home) + tm_symbols(col='red',shape=4,size=0.5,alpha=0.8)+
tm_compass(position=c("right", "bottom"))+
tm_scale_bar(position=c("right", "bottom"))

, :

( ):
lm(price ~ parking:area_interior)
:
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 33776.10 22175.97 1.523 0.129
## parkingFALSE:area_interior 444.28 23.54 18.876 <2e-16 ***
## parkingTRUE:area_interior 523.01 19.65 26.614 <2e-16 ***
.. 444$ 33, +523$.
, 443k$, [433k$ — 453k$]
, , :

.. , .. . , . , , , generalized linear model inverse Gaussian distribution , - , :

: 435k$, 95% [419k$ — 450k$] — , .
, , , — .
, , — .. , , ( X X ) .
, () , ( , ).

generalized linear model inverse Gaussian distribution :
glm(price_sqft ~ parking + bedrooms,family=inverse.gaussian(link="log")
:
## (Intercept) parkingTRUE bedrooms2 bedrooms3 bedrooms4
## 503.1981961 1.1215828 0.9720589 0.9662187 0.8325715
.. , 503$, 12% , — 2.8%, 3 — 3.3%, 4 17%, .
430k$ [ 413k$ — 448k$]
. .
- , - , — - , ?
, loess.

, — - .

, . , ( ) .
“ ” Generalized additive model
, . R mgcv gam:
gam(price_sqft ~ parking + bedrooms + s(start_date, k=24), family=inverse.gaussian(link="log"))
, , inverse Gaussian distribution, , , 24 . gam — , k .
( 2 ):

, : 429k [413k-447k], . . , .
, , .

, 60 . , .
, , . , 1, - :
#
selected_mls=17758383
# 2
max_distance=2000
#
plex_pe<-prop_geo_p %>% filter(type!='Apartment', type!='House')
ref<-plex_pe%>%filter(mls==selected_mls)
#
search_roi <- st_buffer(ref, max_distance)
# , -
result <- st_intersection(plex_pe %>% filter(mls!=selected_mls), search_roi) %>%
filter(area_interior<10000, area_interior>100,area_land>0,price<1e7,price>100 )
:

:

, , , - — , ( XX ), ..
, 523k$, [ 570k$ — 620k$]
, . , . sf :
, (), , :
aggregate(filter(kijiji_geo_p,bedrooms==2)%>%dplyr::select(price), mtl_p, median, join = st_contains)

, . . .
, :
gam(price_sqft ~ type + bedrooms + parking + s(x,y,k=100), family=inverse.gaussian(link="log"))
, 100:
pred_rent_whole <- raster(extent(mtl_land),res=100)
crs(pred_rent_whole)<-crs(mtl_land)
my_predict<-function(...) predict(...,type="response")
pred_rent_whole<- raster::interpolate(pred_rent_whole, model_rent_geo_whole, fun=my_predict, xyOnly=T,const=data.frame(bedrooms=2))
#
pred_rent_whole <- mask(pred_rent_whole, mtl_land)
tmap:
tm_shape(osm_mtl)+tm_rgb(alpha=0.6)+
tm_shape(mtl_arr) + tm_borders(alpha=0.8, col='black')+
tm_shape(pred_rent_whole)+tm_raster(style="cont",alpha=0.7, title='$')+ tm_shape(subway_stop_p%>%dplyr::select(stop_name))+tm_symbols(col='blue',alpha=0.2,size=0.03)+
tm_shape(subway_p)+tm_lines(col='blue',alpha=0.2)+
tm_compass(position=c("right", "bottom"))+
tm_scale_bar(position=c("left", "bottom"))+
tm_layout(scale=1.5)

— .
, .

, .

, ( /( * ).
.

( / ).

, , ( ).

, R evaluar qué, cuándo y dónde comprar o vender. Pero la vida es una cosa más complicada, en la aplicación real no hay suficiente conocimiento del precio de venta real (en nuestra área esto está disponible solo para agentes inmobiliarios registrados). Por lo tanto, no debe esperar que los pronósticos obtenidos coincidan con la realidad en un 100%. En general, quien no se escondió no es mi culpa.
Fuente
Todos los datos y el código fuente están en el repositorio . ¡Compra nuestros elefantes!
Bono para aquellos que han leído hasta el final
Mapa interactivo con los resultados: http://www.ilmarin.info/re_mtl/