Mapping walking time on OSM data with r5r

The topic of day 5 in the #30DayMapChallenge is ‘OpenStreetMap’. So here is a quick reproducible example showing how one can use OpenStreetMap data and the r5r package to calculate travel times.

options(java.parameters = "-Xmx4G")

library(r5r)
library(geobr)
library(sf)
library(ggplot2)
library(here)
library(osmextract)
library(data.table)
library(magrittr)


# create subdirectories "data" and "img"
dir.create(here::here("data"))
dir.create(here::here("img"))


# get city boundaries
city <- 'Rio de Janeiro'
city_code <- lookup_muni(name_muni = city)
city_boundary <- read_municipality(code_muni = city_code$code_muni, simplified = F)


# define city center
city_center_df <- data.frame(id='center', lon=-43.182811, lat=-22.906906)
city_center_sf <- sfheaders::sfc_point(obj = city_center_df, x='lon', y='lat')
st_crs(city_center_sf) <- 4326

# define buffer area of analysis 3 Km
buff <- st_buffer(city_center_sf, dist = 3000)

# crs
city_boundary <- st_transform(city_boundary, 4326)
city_center_sf <- st_transform(city_center_sf, 4326)
buff_bb <- st_bbox(buff)


# get OSM data
osmextract::oe_download(provider = 'openstreetmap_fr',
                        file_url = osmextract::oe_match("Rio De Janeiro")[[1]],
                        download_directory = here::here("data"), force_download = T)


# build routing network
r5r_core <- r5r::setup_r5(data_path = here::here("data"), verbose = FALSE)

# get street network as sf
street_network <- r5r::street_network_to_sf(r5r_core)

# drop network outside our buffer
edges_buff <- street_network$edges[buff, ] %>% st_intersection(., buff)
vertices_buff <- street_network$vertices[buff, ] %>% st_intersection(., buff)
city_boundary_buff <- st_intersection(city_boundary, buff)
plot(city_boundary_buff)

# add id to vertices
vertices_buff$id <- vertices_buff$index


# calculate travel times to city center 
tt <- r5r::travel_time_matrix(r5r_core,
                              origins = vertices_buff,
                              destinations = city_center_df,
                              mode = 'walk')


# add travel time info to street network
tt$fromId <- as.numeric(tt$fromId)
setDT(edges_buff)[tt, on=c('from_vertex'='fromId'), travel_time := i.travel_time]
edges_buff <- st_sf(edges_buff)

Now we only need to plot and save the figure.

# figure
temp <- ggplot() + 
        geom_sf(data=buff, fill='lightblue', color=NA)  +
        geom_sf(data=city_boundary_buff, fill='white', size=.3)  +
        geom_sf(data=buff, fill='gray90', color=NA, alpha=.5)  +
        geom_sf(data=edges_buff, aes(color=travel_time, size=length))  +
        geom_sf(data=city_center_sf, color='red', size=.5) +
        scale_size_continuous(range = c(0.1, .8), guide='none') +
        scale_color_viridis_c(direction = -1) +
  labs(title='Walking time to city center',
       subtitle = 'Rio de Janeiro',
       caption = 'Image by @UrbanDemog using r5r and osmextract',
       color='Minutes') +
  coord_sf(xlim = c(buff_bb[[1]], buff_bb[[3]]), 
                 ylim = c(buff_bb[[2]], buff_bb[[4]]), expand = FALSE) + 
  theme_void() +
  theme(plot.background = element_rect(fill = "white", color='white'),
        plot.title = element_text(color = "gray20"),
        plot.subtitle = element_text(color = "gray40"),
        plot.caption = element_text(color = "gray"))
        
# save figure
ggsave(temp, file=here::here("img", "aa32k.png"), 
       dpi=300, width = 14, height = 14, units = 'cm')

comments powered by Disqus

Related