About Zillow.com

Zillow.com is a large online real estate platform that provides information and tools related to buying, selling, renting, and financing homes. The platform’s offerings include property listings, home value estimates, rental listings, and housing market data for consumers, researchers, and professionals.

Zillow’s publicly available market metrics include the Zillow Observed Rent Index (ZORI), which measures typical market rents based on observed rental listings. The index is designed to track rent changes over time rather than asking rents for specific units. At the ZIP‑code level, ZORI values show the estimated typical rent for a given area, reflecting local rental market conditions and how rents are rising or falling within relatively small geographic markets. The data are useful for comparing neighborhood-level rent trends and affordability across cities and regions.

ZORI estimates for MTSU-area ZIP codes

Below is a map showing the four ZIP codes closest to MTSU’s campus and, below the map, a table of monthly ZORI estimates for each ZIP code between Jan. 1, 2024 and Feb. 1, 2026.


MTSU-area ZIP codes and ZORI estimates

Zillow Observed Rent Index (ZORI)
Monthly by ZIP — Murfreesboro, TN
Month 37127 37128 37129 37130
2024-01-01 1635 1643 1768 1442
2024-02-01 1641 1651 1744 1437
2024-03-01 1659 1684 1750 1435
2024-04-01 1695 1707 1765 1430
2024-05-01 1699 1721 1789 1448
2024-06-01 1688 1708 1804 1459
2024-07-01 1697 1709 1816 1486
2024-08-01 1688 1711 1837 1493
2024-09-01 1689 1717 1828 1481
2024-10-01 1693 1707 1833 1469
2024-11-01 1701 1719 1801 1461
2024-12-01 1690 1715 1809 1448
2025-01-01 1663 1715 1795 1444
2025-02-01 1666 1694 1793 1462
2025-03-01 1656 1696 1788 1495
2025-04-01 1650 1696 1813 1507
2025-05-01 1670 1700 1834 1497
2025-06-01 1685 1708 1846 1500
2025-07-01 1724 1711 1827 1520
2025-08-01 1705 1733 1826 1521
2025-09-01 1681 1730 1824 1538
2025-10-01 1656 1735 1829 1530
2025-11-01 1671 1712 1807 1525
2025-12-01 1685 1710 1804 1513
2026-01-01 1704 1723 1809 1508
2026-02-01 1699 1722 1823 1512

Code

Here is the R code that produced the map and table:

# =============================================================================
# ZORI by ZIP for Murfreesboro, TN — streamlined
# Download → Clean → Reshape → Visualize (plotly) → Tabulate (gt) → Map (leaflet)
# =============================================================================

# ---- Parameters --------------------------------------------------------------
CITY          <- "Murfreesboro"
STATE         <- "TN"
MURF_ZIPS     <- c("37127", "37128", "37129", "37130")
MONTH_WINDOW  <- 25  # change to 36 if desired

ZILLOW_URL <- "https://files.zillowstatic.com/research/public_csvs/zori/Zip_zori_uc_sfrcondomfr_sm_month.csv?t=1773853995"

# ---- Libraries ---------------------------------------------------------------
suppressPackageStartupMessages({
  library(readr)
  library(dplyr)
  library(janitor)
  library(lubridate)
  library(tidyr)
  library(plotly)
  library(scales)
  library(gt)
  library(sf)
  library(leaflet)
  library(RColorBrewer)
  library(htmltools)
})

# =============================================================================
# A) Acquire & prepare Zillow ZORI
# =============================================================================
local_file <- tempfile(fileext = ".csv")
download.file(ZILLOW_URL, local_file, mode = "wb")

zori <- read_csv(local_file, show_col_types = FALSE) |>
  clean_names()

# Keep only city/state first (faster pivot)
zori_murf <- zori |>
  filter(state == STATE, city == CITY)

# ---- Pivot then parse date names in mutate() -------------------------
zori_murf_long <- zori_murf |>
  pivot_longer(
    cols = matches("^\\d{1,2}/\\d{1,2}/\\d{4}$|^x?\\d{4}_\\d{2}_\\d{2}$"),
    names_to = "date",
    values_to = "zori"
  ) |>
  mutate(
    date = sub("^x", "", date),
    date = ifelse(
      grepl("/", date),
      as.character(lubridate::mdy(date)),                # m/d/yyyy
      as.character(lubridate::ymd(gsub("_", "-", date))) # yyyy_mm_dd -> yyyy-mm-dd
    ),
    date = as.Date(date)
  ) |>
  arrange(region_name, date)

# =============================================================================
# B) Filter window & visualize
# =============================================================================
most_recent_date <- max(zori_murf_long$date, na.rm = TRUE)
cutoff_date      <- most_recent_date %m-% months(MONTH_WINDOW)

zori_murf_window <- zori_murf_long |>
  filter(date >= cutoff_date, !is.na(zori))

# ---- Plotly line chart -------------------------------------------------------
ZORIplot <- plot_ly(
  data = zori_murf_window,
  x = ~date, y = ~zori,
  color = ~region_name,
  type = "scatter", mode = "lines",
  hoverinfo = "text",
  text = ~paste(
    "ZIP:", region_name,
    "<br>Date:", format(date, "%Y-%m-%d"),
    "<br>ZORI:", dollar(zori)
  )
) |>
  layout(
    title = paste0("ZORI Rent Trends by ZIP — ", CITY, ", ", STATE),
    xaxis = list(title = "Date"),
    yaxis = list(title = "Typical Rent (ZORI estimate, $)"),
    legend = list(title = list(text = "<b>ZIP Code</b>"))
  )

ZORIplot

# =============================================================================
# C) Tables (long → month-level wide → gt)
# =============================================================================
zori_wide <- zori_murf_window |>
  transmute(
    Month = floor_date(date, "month"),
    ZIP   = region_name,
    ZORI  = round(zori, 0)
  ) |>
  group_by(Month, ZIP) |>
  summarize(ZORI = mean(ZORI, na.rm = TRUE), .groups = "drop") |>
  arrange(Month, ZIP) |>
  pivot_wider(names_from = ZIP, values_from = ZORI) |>
  arrange(Month)

ZORISummary <- zori_wide |>
  gt() |>
  tab_header(
    title = "Zillow Observed Rent Index (ZORI)",
    subtitle = paste0("Monthly by ZIP — ", CITY, ", ", STATE)
  )

ZORISummary

# =============================================================================
# D) ZIP code map (ZCTAs)
# =============================================================================
# Download once per session (TIGER/Line ZCTA 2020)
zipfile <- "ZCTAs2020.zip"
if (!file.exists(zipfile)) {
  download.file(
    "https://www2.census.gov/geo/tiger/GENZ2020/shp/cb_2020_us_zcta520_500k.zip",
    zipfile, mode = "wb"
  )
}
unzip(zipfile, exdir = "ZCTAs2020", overwrite = FALSE)

ZCTAMap <- suppressWarnings(read_sf(file.path("ZCTAs2020", "cb_2020_us_zcta520_500k.shp"))) |>
  filter(GEOID20 %in% MURF_ZIPS) |>
  st_make_valid() |>
  st_transform(4326)

zcta_ids <- as.character(ZCTAMap$GEOID20)
n        <- length(zcta_ids)
pal_vec  <- if (n <= 1) "#66C2A5" else if (n <= 8) brewer.pal(max(3, n), "Set2")[seq_len(n)] else colorRampPalette(brewer.pal(8, "Set2"))(n)
pal      <- colorFactor(pal_vec, domain = zcta_ids)

bb   <- st_bbox(ZCTAMap)
lng1 <- as.numeric(bb["xmin"]); lat1 <- as.numeric(bb["ymin"])
lng2 <- as.numeric(bb["xmax"]); lat2 <- as.numeric(bb["ymax"])

FinalMap <- leaflet(options = leafletOptions(minZoom = 6)) |>
  addProviderTiles(providers$Esri.WorldStreetMap, group = "Esri World Street Map") |>
  addProviderTiles(providers$CartoDB.Positron, group = "Light (Positron)") |>
  addPolygons(
    data        = ZCTAMap,
    fillColor   = ~pal(GEOID20),
    fillOpacity = 0.45,
    color       = "#444444",
    weight      = 1.2,
    opacity     = 0.9,
    label       = lapply(sprintf("<strong>ZCTA:</strong> %s", htmlEscape(zcta_ids)), HTML),
    popup       = ~paste0("<b>ZCTA:</b> ", GEOID20),
    highlightOptions = highlightOptions(weight = 3, color = "#000", fillOpacity = 0.55, bringToFront = TRUE)
  ) |>
  fitBounds(lng1, lat1, lng2, lat2) |>
  addLegend("bottomright", pal = pal, values = zcta_ids, title = paste0(CITY, " ZIP codes"), opacity = 0.7) |>
  addLayersControl(baseGroups = c("Esri World Street Map", "Light (Positron)"),
                   options = layersControlOptions(collapsed = TRUE))

FinalMap