---
title: "Location Analysis by Time of Day"
title-block: false
prefer-html: true
format:
  html:
    self-contained: false
execute:
  echo: false
  warning: false
  message: false
---

![](logo.png){width=260px style="float:left; margin-right:12px;"} **Jim Amorin, CAE, MAI, SRA, AI-GRS, CDEI**\
Published: `r format(Sys.Date(), '%B %d, %Y')` <br clear="all">

## Does Time of Day Matter to Retail Success?

Understanding accessibility patterns around a property requires more than just measuring distance. It is about measuring time as well. Drive-time analysis using isochrones reveals which areas fall within a predefined number of minutes of a location, providing critical insights for retail site selection, market analysis, and accessibility studies. However, standard drive-time calculations often assume consistent traffic conditions throughout the day, which rarely reflects reality.

Traffic patterns can dramatically reshape a property's effective market area. A location that enjoys excellent accessibility during midday hours may experience significant constraints during peak commute times, potentially reducing its customer catchment area by 30% or more. For commercial properties—particularly retail and restaurant locations—these temporal variations in accessibility directly impact revenue potential and site viability.

The interactive comparison below demonstrates this phenomenon at Franklin's Barbecue in Austin, Texas. By comparing drive-time isochrones at noon versus 5:30 PM, we can visualize how rush hour traffic compresses the accessible market area. This type of time-aware analysis provides a more accurate picture of a property's true trade area and helps identify optimal locations that maintain strong accessibility across different times of day.

::: callout-note
While access to Franklin's is easier at noon than at rush hour, if you hope to get BBQ, you may want to get in line at the crack of dawn. They ***will run out*** some time after lunch and before the evening rush hour.😀
:::

::: callout-tip
Special thanks to Walker Data for the starting code base which can be found here: <https://walker-data.com/posts/time-aware-isochrones/>
:::

```{r}
#| label: create-maps
library(mapgl)
library(mapboxapi)

mb_access_token("pk.eyJ1IjoiY2FwcmF0ZWNvZGVyIiwiYSI6ImNtOTM2ZnZrZDA1YjUyeHBzdGI5OGowaXAifQ.c8lMaPjq02qyRe_BEOY7AA")

point <- "900 E. 11th Street, Austin, TX 78702"

# Geocode the point
bbq_sf <- mb_geocode(point, output = "sf")

# Isochrones for noon and rush hour
iso_12pm <- mb_isochrone(point, depart_at = "2025-09-11T12:00")
iso_530pm <- mb_isochrone(point, depart_at = "2025-09-11T17:30")

# Add label field for the popup
bbq_sf$popup_text <- "Franklin's BBQ, 900 E. 11th St, Austin"

# Noon map (light background)
map1 <- mapboxgl(bounds = iso_12pm, style = "mapbox://styles/mapbox/light-v11") |>
  add_fill_layer(
    "noon",
    source = iso_12pm,
    fill_color = match_expr(column = "time",
                            values = c(5, 10, 15),
                            stops = c("red", "blue", "green")),
    fill_opacity = 0.4
  ) |>
  add_markers(
    data = bbq_sf,
    popup = "popup_text",
    label = "popup_text",
    marker_color = "red"
  )

# Rush hour map (dark background)
map2 <- mapboxgl(bounds = iso_12pm, style = "mapbox://styles/mapbox/navigation-night-v1") |>
  add_fill_layer(
    "rush_hour",
    source = iso_530pm,
    fill_color = match_expr(column = "time",
                            values = c(5, 10, 15),
                            stops = c("red", "blue", "green")),
    fill_opacity = 0.4
  ) |>
  add_markers(
    data = bbq_sf,
    popup = "popup_text",
    label = "popup_text",
    marker_color = "red"
  )

# Comparison
widget <- compare(
  map1,
  map2,
  swiper_color = "#cc5500"
) |>
  add_legend(
    "Access (12pm vs. 5:30pm)",
    values = c("5 minutes", "10 minutes", "15 minutes"),
    colors = c("red", "blue", "green"),
    patch_shape = iso_530pm[1,],
    type = "categorical",
    style = legend_style(background_opacity = 0.8),
    position = "bottom-left"
  ) |>
  htmlwidgets::prependContent(
    htmltools::tags$div(
      htmltools::HTML('
        <div style="position:absolute; top:10px; left:15px; background:rgba(0,0,0,0.5);
                     color:white; padding:4px 8px; border-radius:4px; font-weight:bold; z-index:999;">
          Noon (12 PM)
        </div>
        <div style="position:absolute; top:10px; right:15px; background:rgba(255,255,255,0.6);
                     color:black; padding:4px 8px; border-radius:4px; font-weight:bold; z-index:999;">
          Rush Hour (5:30 PM - Foods Gone)
        </div>
      ')
    )
  )

# Save widget to separate HTML file
htmlwidgets::saveWidget(widget, "map_widget.html", selfcontained = TRUE)
```

<iframe src="map_widget.html" width="100%" height="600px" style="border:none;">

</iframe>
