Pour vendre quelque chose d'inutile, vous devez d'abord acheter quelque chose d'inutile, mais nous n'avons pas d'argent.
- Trois de Prostokvashino
introduction
Il se trouve que j'habite dans mon appartement (ou condo local) à Montréal. Et une fois, il y a environ un an, j'ai pensé que ce serait bien de déménager chez vous. J'avais déjà une certaine expérience dans l'achat et la vente de logements et, en principe, il serait possible d'aborder cette question simplement, comme le font la majorité des habitants locaux: embaucher un agent immobilier et le laisser s'occuper de toutes les questions, mais ce serait ennuyeux et sans intérêt.
J'ai donc décidé d'aborder cette question scientifiquement. Il y a une tâche: vous devez savoir combien vaut ce que j'ai et où je peux me le permettre. Eh bien, une question passagère - pour comprendre où le vent souffle. Et explorer les calculs de géo-spatiale dans la R .
En principe, il était immédiatement clair que je ne tirerais pas simplement une maison de famille séparée (localement) si je veux rester dans une zone civilisée et frapper le réchauffement climatique avec une balade à vélo quotidienne. Une autre option locale courante consiste à acheter un duplex ou un triplex, c'est-à-dire maisons où il y a deux ou trois appartements: vous vivez dans un,dans le reste, vous élevez des lapinsle reste est remis aux locataires. Puis une autre quantité inconnue apparaît: les revenus locatifs.
Par conséquent, je voulais faire une carte de la ville avec les prix des logements à vendre, les prix de location et aussi pouvoir suivre comment tout cela change au fil du temps.
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 évaluer quoi, quand et où acheter ou vendre. Mais la vie est une chose plus compliquée, dans une application réelle, il n'y a pas assez de connaissance du prix de vente réel (dans notre région, cela n'est disponible que pour les agents immobiliers enregistrés). Il ne faut donc pas s'attendre à ce que les prévisions obtenues coïncident à 100% avec la réalité. En général, celui qui ne s'est pas caché n'est pas de ma faute.
La source
Toutes les données et le code source sont dans le référentiel . Achetez nos éléphants!
Bonus pour ceux qui ont lu jusqu'au bout
Carte interactive avec les résultats: http://www.ilmarin.info/re_mtl/