library(rental) library(cancensus) library(tidyverse) library(sf)
As an example we read the August data for unfurnished listings for Vancouver, Calgary and Toronto.
region_names=c("Vancouver","Calgary","Toronto") regions=list_census_regions('CA16', use_cache = TRUE) %>% filter(level=="CSD",name %in% region_names) geo=get_census(dataset = 'CA16',regions=as_census_region_list(regions),geo_format='sf',level="Regions") start_time="2019-01-01" end_time="2019-02-01" for (i in 1:nrow(geo)) { row=geo[i,] ls <- get_listings(start_time,end_time,row$geometry) summary=ls %>% as.data.frame %>% select("price","beds","size","furnished") %>% filter(!is.na(size),size>0) %>% group_by(beds,furnished) %>% summarize(median=paste0("$",format(median(price),big.mark=",")),median_ppsf=paste0("$",round(median(price/size, na.rm=TRUE),2),"/sf"), count=n()) %>% mutate(name=row$name) print(row$name) print(summary) #print(paste0(row$name," median price: $",format(median(ls$price),big.mark=","))) } #ls %>% filter(beds=="1")
g <- geo %>% filter(name=="Vancouver (CY)") get_rental_summary <- function(g,start_time,end_time) { ls <- get_listings(start_time,end_time,g$geometry) summary=ls %>% as.data.frame %>% select("price","beds","size","furnished") %>% filter(!is.na(size),size>0) %>% group_by(beds,furnished) %>% summarize(median=median(price),median_ppsf=median(price/size, na.rm=TRUE), count=n()) } start_time="2018-01-01" end_time="2019-04-20" plot_data <- get_rental_summary(g,"2019-03-20","2019-04-20") %>% mutate(Year="Jan 2019") %>% bind_rows( get_rental_summary(g,"2018-03-20","2018-04-20") %>% mutate(Year="Jan 2018") ) %>% filter(beds %in% c(1,2,3)) %>% group_by(furnished,beds) %>% select(median_ppsf,Year) %>% spread(key=Year,value=median_ppsf) %>% mutate(change=scales::percent(`Jan 2019`/`Jan 2018`-1)) %>% mutate_at(c("Jan 2019","Jan 2018"),function(x)paste0("$",round(x,2),"/sf")) plot_data %>% knitr::kable()
region_name="Vancouver" regions=list_census_regions('CA16', use_cache = TRUE) %>% filter(level=="CSD",name == region_name) geo=get_census(dataset = 'CA16',regions=as_census_region_list(regions),geo_format='sf',level="Regions") start_time="2017-05-01" end_time="2019-04-20" ls <- get_listings(start_time,end_time,geo$geometry,filter = 'unfurnished',include_title = FALSE) summary=ls %>% as.data.frame %>% select("price","beds") %>% group_by(beds) %>% summarize(median=paste0("$",format(median(price),big.mark=",")), count=n()) %>% mutate(name=region_name)
plot_data <- ls %>% mutate(year_month=strftime(post_date,"%Y-%m")) %>% mutate(beds=case_when(as.integer(beds)<=3 ~ beds,TRUE ~ "4+")) %>% filter(beds!="4+") %>% mutate(ppsf=price/size) %>% filter(!is.na(ppsf)) ggplot(plot_data, aes(x=year_month, y=ppsf)) + #geom_point(size=0.01,alpha=0.2) + geom_boxplot(outlier.shape = NA) + #scale_color_discrete(name="Bedrooms") + theme_bw() + scale_y_continuous(labels=function(d)paste0("$",round(d,1),"/sf"),limits = c(0,6)) + facet_wrap("beds") + theme(axis.text.x = element_text(angle = 60, hjust = 1)) + labs(title=paste0("City of Vancouver unfurnished listings by number of bedrooms"),x="Date",y="Asking Rent per sf") #ggplot(nbhds, aes(fill=NAME)) +geom_sf()
plot_data %>% st_set_geometry(NULL) %>% group_by(year_month,beds) %>% summarize_at(c("price","ppsf"),median,na.rm=TRUE) %>% filter(year_month %in% c("2018-03","2019-03")) %>% mutate(year=substr(year_month,1,4) %>% as.integer, month=substr(year_month,6,7)) %>% left_join((.) %>% mutate(year=year+1) %>% select(year,month,beds,price,ppsf),by=c("year","month","beds")) %>% mutate(change=price.x/price.y-1, changesf=ppsf.x/ppsf.y-1)
Fold in nbhd data
ls<-st_as_sf(ls) %>% st_join( st_read(file.path(getOption("custom_data_path"),"local_area_boundary_shp/local_area_boundary.shp")) %>% st_transform(4326))
ls %>% filter(NAME %in% c("Downtown","West End")) %>% group_by(furnished,beds) %>% summarize(price=median(price))
ggplot(ls %>% filter(as.integer(beds)<3, as.integer(beds)>0, price<6000, price>500), aes(x=post_date, y=price, color=beds,group=beds)) + #geom_point(size=0.01,alpha=0.2) + geom_smooth(method = "loess", se = FALSE) + scale_color_discrete(name="Bedrooms") + theme_bw() + facet_wrap("NAME") + labs(title=paste0("Listings (unfurnished) ",format(nrow(ls))),x="Date",y="Asking Rent") #ggplot(nbhds, aes(fill=NAME)) +geom_sf()
ggplot(ls %>% group_by(NAME) %>% filter(n()>5000) %>% ungroup %>% mutate(ppsf=price/size), aes(x=post_date, y=ppsf)) + #geom_point(size=0.01,alpha=0.2) + geom_smooth(method = "loess", se = FALSE) + #scale_color_discrete(name="Bedrooms") + theme_bw() + facet_wrap("NAME") + labs(title=paste0("Listings (unfurnished) ",format(nrow(ls))),x="Date",y="Asking Rent per sf") #ggplot(nbhds, aes(fill=NAME)) +geom_sf()
area="Renfrew-Collingwood" plot_data <- ls %>% filter(NAME==area,as.integer(beds)<3, price<5000) %>% mutate(beds=ifelse(as.integer(beds)>=5,"5+",beds)) ggplot(plot_data, aes(x=post_date, y=price, color=beds,group=beds)) + geom_point(size=0.01,alpha=0.2) + geom_smooth(method = "loess", se = FALSE) + scale_color_discrete(name="Bedrooms") + theme_bw() + labs(title=paste0(area," Listings (unfurnished) ",format(nrow(plot_data))),x="Date",y="Asking Rent")
plot_data <- ls %>% filter(as.integer(beds)<3, price<6000, price>500) %>% mutate(ppsf=price/size) %>% filter(!is.na(ppsf) & ppsf<7.5) ggplot(plot_data, aes(x=post_date, y=ppsf, color=beds,group=beds)) + geom_point(size=0.01,alpha=0.2) + geom_smooth(method = "loess", se = FALSE) + theme_bw()
plot_data <- ls %>% filter(as.integer(beds)<=2) %>% mutate(beds=ifelse(as.integer(beds)>=5,"5+",beds), type=paste0(beds, ifelse(downtown," downtown",""))) # totals <- plot_data %>% # group_by(downtown,beds) %>% summarize(price,sub) ggplot(plot_data, aes(x=post_date, y=price, color=type,group=type)) + geom_point(size=0.01,alpha=0.2) + scale_color_brewer(palette = "Paired") + geom_smooth(method = "loess", se = FALSE) + theme_bw()
bg_color="#c0c0c0" theme_opts<-list(theme(panel.grid.minor = element_blank(), #panel.grid.major = element_blank(), #bug, not working panel.grid.major = element_line(colour = bg_color), panel.background = element_rect(fill = bg_color, colour = NA), plot.background = element_rect(fill=bg_color, size=1,linetype="solid"), axis.line = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank(), axis.ticks = element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank()))
library(sf) library(ggplot2) geo=get_census(dataset = 'CA16',regions=list(CMA="59933"),geo_format='sf',level="Regions") ls <- get_listings(start_time,end_time,geo$geometry,beds=c(1),filter = 'unfurnished') summary=ls %>% as.data.frame %>% select("price","beds") %>% group_by(beds) %>% summarize(median=paste0("$",format(median(price),big.mark=","))) %>% mutate(name=row$name) cts=get_census(dataset = 'CA16',regions=list(CMA="59933"),geo_format='sf',level="CSD") min_listings=10 median_rent <- function(v){ result <- ifelse(length(v)>min_listings, median(v),NA) return(result) } aggregate_listings <- aggregate(cts %>% select("GeoUID"),ls,function(x){x}) data <- aggregate(ls %>% select("price"),cts,median_rent) cutoffs=as.integer(quantile(data$price, probs=seq(0,1,0.1), na.rm=TRUE)) labels=factor(as.character(seq(1,length(cutoffs)-1) %>% lapply(function(i){return(paste0(cutoffs[i]," - ",cutoffs[i+1]))})),order=TRUE) colors=setNames(RColorBrewer::brewer.pal(length(labels),"RdYlBu"),labels) data$discrete_price= data$price %>% cut(breaks=cutoffs, labels=labels) ggplot() + geom_sf(data=cts, fill="#808080", size=0.1) + geom_sf(data=data, aes(fill = discrete_price), size=0.1) + scale_fill_brewer(palette='RdYlBu', direction=-1, na.value="#808080",name="Median Price") + labs(title="August Studio and 1 Bedroom Unfurnished Median Ask") + theme_opts
library(ggbeeswarm) library(gridExtra) regions=as_census_region_list(search_census_regions("Vancouver",'CA16','CMA')) geo=get_census(dataset = 'CA16',regions=regions,geo_format='sf',level="Regions") ls <- get_listings(start_time,end_time,geo$geometry,beds=c(1),filter = 'unfurnished',sanity=c(400,4000)) summary=ls %>% as.data.frame %>% select("price","beds") %>% group_by(beds) %>% summarize(median=paste0("$",format(median(price),big.mark=","))) %>% mutate(name=row$name) geos=get_census(dataset = 'CA16',regions=regions,geo_format='sf',level="CSD") %>% st_join(ls) top_munis <- geos %>% group_by(name) %>% summarize(count=length(name)) %>% top_n(5,count) %>% pull("name") plot_data <- geos %>% filter(name %in% top_munis) %>% rename(Municipality=name) title="Distribution of Unfurnished 1br Rents, September 2017" p1 <- ggplot(plot_data) + geom_density(aes(x=price, color=Municipality)) + labs(title=title) p2 <- ggplot(plot_data, aes(Municipality, price))+ geom_violin(aes(fill=Municipality )) + #geom_beeswarm(pch = 1, col='white', cex=0.8, alpha=0.6) + labs(title=title) grid.arrange(p1, p2, ncol=1)
region_name="Coquitlam" #"Richmond" regions=as_census_region_list(search_census_regions(region_name,'CA16','CSD') %>% filter(name==region_name)) geo=get_census(dataset = 'CA16',regions=regions,geo_format='sf',level="Regions") ls <- get_listings(start_time,end_time,geo$geometry,beds=c(1),filter = 'unfurnished',sanity=c(400,4000)) summary=ls %>% as.data.frame %>% select("price","beds") %>% group_by(beds) %>% summarize(median=paste0("$",format(median(price),big.mark=","))) %>% mutate(name=row$name) cutoffs=c(400,1350,4000) labels=factor(as.character(seq(1,length(cutoffs)-1) %>% lapply(function(i){return(paste0(cutoffs[i]," - ",cutoffs[i+1]))})),order=TRUE) colors=setNames(c("turquoise","purple"),labels) ls$discrete_price= ls$price %>% cut(breaks=cutoffs, labels=labels) #ls <- cbind(ls,st_coordinates(st_transform(ls,102002)$location)) ls <- cbind(ls,st_coordinates(ls$location)) library(ggmap)
base <- get_map(paste0(region_name,", Canada"), zoom=12, source = "stamen", maptype = "toner", crop = T) #ggplot() + ggmap(base) + #geom_sf(data=geo, fill="#808080", size=0.1) + #coord_sf(crs=st_crs(102002)) + geom_point(data=ls , aes(color = discrete_price, x=X, y=Y), shape=21, size=2) + scale_fill_manual(palette=colors) + labs(title="August Studio and 1 Bedroom Unfurnished Median Ask",color="Price") + theme_opts
region_name="Vancouver" regions=as_census_region_list(search_census_regions(region_name,'CA16','CSD') %>% filter(name==region_name)) geo=get_census(dataset = 'CA16',regions=regions,geo_format='sf',level="Regions") ls <- get_listings(start_time,end_time,geo$geometry,beds=c(1),filter = 'unfurnished',sanity=c(400,4000)) ls$year_month <- factor(substr(ls$post_date,0,7),ordered = TRUE) #ls$year_month_day <- factor(substr(ls$post_date,0,10),ordered = TRUE) #ls %>% group_by(year_month) %>% summarize(count=length(year_month)) %>% as.data.frame %>% select("year_month","count") #ls %>% group_by(year_month_day) %>% summarize(count=length(year_month_day)) %>% as.data.frame %>% select("year_month_day","count") plot_data <- ls %>% as.data.frame %>% select("price","year_month") title="Distribution of Unfurnished 1br Rents, City of Vancouver" p1 <- ggplot(plot_data) + geom_density(aes(x=price, color=year_month)) + labs(title=title, color="Year-Month") p2 <- ggplot(plot_data, aes(year_month, price))+ geom_violin(aes(fill=year_month )) + #geom_beeswarm(pch = 1, col='white', cex=0.8, alpha=0.6) + labs(title=title, fill="Year-Month", x="Year-Month") grid.arrange(p1, p2, ncol=1)
library(ggbeeswarm) library(gridExtra) region_names=c("Vancouver","Toronto","Victoria","Calgary") regions= as_census_region_list(do.call(rbind,lapply(region_names,function(region_name){return((search_census_regions(region_name,'CA16','CSD') %>% filter(name==region_name)))}))) geo=get_census(dataset = 'CA16',regions=regions,geo_format='sf',level="Regions") geometry=st_union(geo$geometry) beds=2 ls <- get_listings(start_time,end_time,geometry,beds=c(beds),filter = 'unfurnished',sanity=c(400,5000)) summary=ls %>% as.data.frame %>% select("price","beds") %>% group_by(beds) %>% summarize(median=paste0("$",format(median(price),big.mark=","))) %>% mutate(name=row$name) geos=get_census(dataset = 'CA16',regions=regions,geo_format='sf',level="CSD") %>% st_join(ls) plot_data <- geos %>% as.data.frame %>% select("name","price") %>% rename(Municipality=name) title=paste0("Distribution of Unfurnished ",beds,"br Rents, August 2017") p1 <- ggplot(plot_data) + geom_density(aes(x=price, color=Municipality)) + labs(title=title) p2 <- ggplot(plot_data, aes(Municipality, price))+ geom_violin(aes(fill=Municipality )) + #geom_beeswarm(pch = 1, col='white', cex=0.8, alpha=0.6) + labs(title=title) grid.arrange(p1, p2, ncol=1)
#geo=sf::read_sf("../data/custom_region.geojson") geo=sf::read_sf("../data/victoria_stainsbury.geojson") ls <- get_listings("2017-06-01","2017-09-01",geo$geometry,filter = 'unfurnished') summary=ls %>% as.data.frame %>% select("price","beds") %>% group_by(beds) %>% summarize(median=paste0("$",format(median(price),big.mark=","))) %>% mutate(name=row$name) ggplot(ls, aes(beds, price))+ geom_violin(aes(fill=beds )) + #geom_beeswarm(pch = 1, col='white', cex=0.8, alpha=0.6) + labs(title="June-August 1br unfurnished Custom Region")
cutoffs=c(400,1050,4000) labels=factor(as.character(seq(1,length(cutoffs)-1) %>% lapply(function(i){return(paste0(cutoffs[i]," - ",cutoffs[i+1]))})),order=TRUE) colors=setNames(c("turquoise","purple"),labels) ls$discrete_price= ls$price %>% cut(breaks=cutoffs, labels=labels) ls <- cbind(ls,st_coordinates(ls$location)) base <- get_map(location=c(-122.84594535827637, 49.18422801616818), zoom=15, source = "stamen", maptype = "toner", crop = T) #ggplot() + ggmap(base) + #geom_sf(data=geo, fill="#808080", size=0.1) + #coord_sf(crs=st_crs(102002)) + geom_point(data=ls , aes(color = discrete_price, x=X, y=Y), shape=21, size=4) + scale_fill_manual(palette=colors) + geom_polygon(data= fortify(as(geo,"Spatial")), aes(x=long, y=lat), fill=NA, size=0.5,color='blue') + labs(title="August 1 Bedroom Unfurnished Median Ask",color="Price") + theme_opts
my_theme <- list( theme_minimal(), theme(axis.text = element_blank(), axis.title = element_blank(), axis.ticks = element_blank(), panel.grid.major = element_line(colour = "white"), panel.grid.minor = element_line(colour = "white"), panel.background = element_blank(), axis.line = element_blank()) )
library(tidyverse) library(cancensus) library(rental) library(sf) regions=list_census_regions('CA16', use_cache = TRUE) %>% filter(level=="CMA",name == "Vancouver") geo=get_census(dataset = 'CA16',regions=as_census_region_list(regions),geo_format='sf',level="CT") start_time="2017-09-01" end_time="2017-12-07" ppsf_formatter <- function(x){return(paste0("$",round(x,2),"/sf"))} ls <- get_listings(start_time,end_time,st_union(geo$geometry),beds=c('0','1','2'),filter = 'unfurnished') %>% mutate(ppsf=price/size) geo_listings <- st_join(geo, filter(ls,!is.na(ppsf))) %>% group_by(GeoUID) %>% summarize(ppsf=median(ppsf),count=n()) ggplot(geo_listings %>% mutate(ppsf=ifelse(count>=5,ppsf,NA)) %>% st_as_sf) + geom_sf(aes(fill=ppsf),size=NA) + scale_fill_viridis_c(name="Asking Rent/sf", option="magma") + labs(title="October 1 through Dec 7 Asking Rent/sf") + my_theme
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.