San Antonio and Austin Isochrones

Author

Justin Pons

Goal

Find properties for sale that are within a 50 minute drive of both Austin and San Antonio downtowns.

library(tidyverse)
library(leaflet)
library(osrm)
library(sf)

Coordinates of Austin and San Antonio Centers

points <- 
  tibble::tribble(
    ~Name,~Lat,~Long,
    "San Antonio",  29.424349,  -98.491142,
    "Austin",   30.266666,  -97.733330
  )

pointsCopy <- points
points <- points |> 
  st_as_sf(coords = c("Long", "Lat")) |>  
    st_set_crs("WGS84")

Isochrone

An isochrone map in geography and urban planning is a map that depicts the area accessible from a point within a certain time threshold.

saDrive <- 
  osrmIsochrone(loc = points |> filter(Name == "San Antonio") |> select(geometry), 
                  breaks = seq(from = 0,
                               to = 50, 
                               by = 50),
                  res=50)

austinDrive <- 
  osrmIsochrone(loc = points |> filter(Name == "Austin") |> select(geometry), 
                  breaks = seq(from = 0,
                               to = 50, 
                               by = 50),
                  res=50)

Powered by OpenStreetMap, two isochrones are generated. The isochrones begin in the center of the two cities and extend as far as you can drive in 50 minutes under ideal conditions.

leaflet() |> 
  setView(mean(pointsCopy$Long), mean(pointsCopy$Lat), zoom = 8) |> 
  addTiles() |>  
  addMarkers(lng = pointsCopy$Long, pointsCopy$Lat, label = pointsCopy$Name) |> 
  addPolygons(fill=TRUE, stroke=TRUE, color = "black",
              fillColor = "blue",
              weight=0.5, fillOpacity=0.2,
              data = saDrive$geometry,
              group = "Drive Time") |> 
  addPolygons(fill = T, stroke = T, color = "black",
              fillColor = "red",
              weight=.5, fillOpacity = .2,
              data = austinDrive,
              group = "Drive Time")

Intersection

Using the R package sf, a geoprocessing package, the intersection of the two isochrones is determined. A polygon boundary is mapped to show the extent of the intersection. Properties within this boundary are 50 minutes from both Austin and San Antonio centers.

sf_use_s2(FALSE)
inter <- 
  st_intersection(saDrive$geometry,austinDrive$geometry)

interCenter <- 
  st_centroid(inter)
leaflet() |> 
  setView(-98.043237, 29.762738, zoom = 11) |> 
  addTiles() |>  
  addPolygons(fill=F, stroke=TRUE, color = "red",
              data = inter,
              group = "Drive Time")

Properties for Sale

The next step would be to connect with a real estate API such as Zillow to dynamically import current listings, however I couldn’t obtain access. Then, listings that are contained in the boundary would be displayed.

adresses <- 
  tribble(
    ~Address,~Latitude,~Longitude,~Value,~SqFt,
    "110 Highwater Ln, New Braunfels, TX 78130",29.769070,-98.037140,1325000,1792,
    "5744 Tug, New Braunfels, TX 78130",29.752520,-98.042560,689990,3050
    )
leaflet() |> 
  setView(-98.043237, 29.762738, zoom = 12) |> 
  addTiles() |>  
  addPolygons(fill=F, stroke=TRUE, color = "red",
              data = inter,
              group = "Drive Time") |> 
  addMarkers(lng = adresses$Longitude, adresses$Latitude, label = adresses$Address)

Next Steps

Connect to a real estate API to collect current listings in a geographic area. For instance, the county the center of the polygon resides in. Geocode the addresses. Geocoding is the process of converting addresses to geographic coordinates. Next, using the sf package, find those listings’ coordinates that are contained by the intersection polygon. Include attributes such as value and square footage.

Use Extension

This technique can be used in a variety of analyses:

  • Use census data to calculate disparity in access to hospitals, grocery stores, libraries, and schools among races, income groups, and age groups.
  • Mapping walkability of urban centers
  • Comparison of public transit vs. personal vehicle commute times