Exploring the cost of rent in Nashville-area ZIP codes

Nashville FMR, by size and ZIP
ZIP Studio BR1 BR2 BR3 BR4 ZIP_Average
37069 2380 2470 2740 3460 4260 3062
37135 2380 2470 2740 3460 4260 3062
37220 2380 2470 2740 3460 4260 3062
37179 2350 2440 2700 3410 4200 3020
37201 2260 2350 2600 3280 4040 2906
37027 2220 2300 2550 3220 3960 2850
37219 2170 2260 2500 3160 3890 2796
37065 2150 2230 2470 3120 3840 2762
37068 2150 2230 2470 3120 3840 2762
37067 2120 2200 2440 3080 3790 2726
37215 2080 2160 2390 3020 3720 2674
37205 2070 2150 2380 3010 3700 2662
37014 2070 2150 2380 3000 3700 2660
37204 2040 2120 2350 2970 3650 2626
37122 2030 2100 2330 2940 3620 2604
37064 1980 2060 2280 2880 3540 2548
37221 1950 2020 2240 2830 3480 2504
37037 1940 2010 2230 2820 3470 2494
37174 1840 1890 2220 2810 3230 2398
37086 1820 1890 2090 2640 3250 2338
37214 1780 1850 2050 2590 3190 2292
37153 1760 1830 2020 2560 3140 2262
37203 1740 1810 2000 2530 3110 2238
37046 1700 1770 2000 2550 3030 2210
37209 1700 1770 1960 2480 3050 2192
37013 1680 1740 1930 2440 3000 2158
37128 1680 1740 1930 2440 3000 2158
37212 1680 1740 1930 2440 3000 2158
37208 1670 1730 1920 2430 2980 2146
37213 1670 1740 1920 2420 2980 2146
37206 1640 1710 1890 2390 2940 2114
37216 1640 1710 1890 2390 2940 2114
37228 1640 1710 1890 2390 2940 2114
37011 1630 1690 1870 2360 2910 2092
37024 1630 1690 1870 2360 2910 2092
37062 1630 1690 1870 2360 2910 2092
37070 1630 1690 1870 2360 2910 2092
37116 1630 1690 1870 2360 2910 2092
37129 1630 1690 1870 2360 2910 2092
37202 1630 1690 1870 2360 2910 2092
37222 1630 1690 1870 2360 2910 2092
37224 1630 1690 1870 2360 2910 2092
37229 1630 1690 1870 2360 2910 2092
37232 1630 1690 1870 2360 2910 2092
37236 1630 1690 1870 2360 2910 2092
37238 1630 1690 1870 2360 2910 2092
37240 1630 1690 1870 2360 2910 2092
37243 1630 1690 1870 2360 2910 2092
37246 1630 1690 1870 2360 2910 2092
37076 1570 1630 1810 2290 2810 2022
37138 1550 1610 1780 2250 2770 1992
37211 1550 1610 1780 2250 2770 1992
37217 1550 1610 1780 2250 2770 1992
37072 1520 1580 1750 2210 2720 1956
37089 1520 1580 1750 2210 2720 1956
37131 1520 1580 1750 2210 2720 1956
37133 1520 1580 1750 2210 2720 1956
37090 1500 1560 1730 2180 2680 1930
37060 1470 1540 1710 2170 2620 1902
37167 1450 1510 1670 2110 2600 1868
37115 1440 1500 1660 2100 2580 1856
37210 1430 1490 1650 2080 2560 1842
37127 1410 1460 1620 2050 2520 1812
37218 1410 1460 1620 2050 2520 1812
37143 1400 1450 1610 2030 2500 1798
37189 1370 1420 1570 1980 2440 1756
37085 1350 1410 1550 1960 2420 1738
37015 1330 1390 1540 1940 2390 1718
37130 1300 1350 1490 1880 2320 1668
37132 1300 1350 1490 1880 2320 1668
38476 1270 1310 1470 1860 2280 1638
37020 1270 1300 1460 1890 2240 1632
37207 1270 1320 1460 1840 2270 1632
37025 1270 1300 1460 1840 2240 1622
37080 1270 1300 1460 1840 2240 1622
37118 1270 1300 1460 1840 2240 1622
37149 1270 1300 1460 1840 2240 1622
37160 1270 1300 1460 1840 2240 1622
37180 1270 1300 1460 1840 2240 1622
38401 1270 1300 1460 1840 2240 1622

Map of Nashville Zip Codes

# Getting and loading required packages

if (!require("tidyverse"))
  install.packages("tidyverse")
if (!require("openxlsx"))
  install.packages("openxlsx")
if (!require("gtExtras"))
  install.packages("gtExtras")
if (!require("leafpop"))
  install.packages("leafpop")
if (!require("sf"))
  install.packages("sf")
if (!require("mapview"))
  install.packages("mapview")
if (!require("RColorBrewer"))
  install.packages("RColorBrewer")
if (!require("tidycensus"))
  install.packages("tidycensus")

library(tidyverse)
library(openxlsx)
library(gtExtras)
library(readxl)
library(sf)
library(mapview)
library(leafpop)
library(RColorBrewer)
library(tidycensus)

# Reading data from:
# https://www.huduser.gov/portal/datasets/fmr/fmr2025/fy2025_safmrs.xlsx
# Note that you are downloading the 2025 data. We have been working with 2024 data.
# The data frame should have 51,899 observations of 18 variables

download.file("https://www.huduser.gov/portal/datasets/fmr/fmr2025/fy2025_safmrs.xlsx", "rent.xlsx", mode = "wb")

FMR <- read_xlsx(path = "rent.xlsx", .name_repair = "universal")

# Making a list of Nashville-area ZIP codes

ZIPList <- c(
  "37135",
  "37215",
  "37064",
  "37060",
  "37014",
  "37122",
  "37027",
  "37046",
  "37221",
  "37153",
  "37210",
  "37202",
  "37024",
  "37218",
  "37062",
  "37179",
  "37025",
  "37206",
  "37065",
  "37214",
  "37067",
  "37246",
  "37068",
  "37167",
  "37069",
  "37189",
  "37070",
  "37204",
  "37072",
  "37208",
  "37076",
  "37212",
  "37080",
  "37216",
  "37085",
  "37020",
  "37086",
  "38476",
  "37089",
  "37160",
  "37090",
  "37174",
  "37115",
  "37180",
  "37116",
  "37201",
  "37118",
  "37203",
  "37015",
  "37205",
  "37127",
  "37207",
  "37128",
  "37209",
  "37129",
  "37211",
  "37130",
  "37213",
  "37220",
  "37037",
  "37222",
  "37217",
  "37228",
  "37219",
  "37232",
  "37013",
  "37131",
  "37224",
  "37132",
  "37229",
  "37133",
  "37236",
  "37238",
  "37240",
  "37243",
  "37138",
  "38401",
  "37143",
  "37011",
  "37149"
)

# Filtering for Nashville-area ZIP codes and
# selecting columns of interest
# FMR_Nash data frame should have 80 observations of six variables

FMR_Nash <- FMR %>%
  filter(ZIP.Code %in% ZIPList) %>%
  select(ZIP.Code, SAFMR.0BR, SAFMR.1BR, SAFMR.2BR, SAFMR.3BR, SAFMR.4BR) %>%
  distinct()

# Renaming the columns

colnames(FMR_Nash) <- c("ZIP", "Studio", "BR1", "BR2", "BR3", "BR4")

FMR_Nash <- FMR %>%
  filter(ZIP.Code %in% ZIPList) %>%
  select(ZIP.Code, SAFMR.0BR, SAFMR.1BR, SAFMR.2BR, SAFMR.3BR, SAFMR.4BR) %>%
  distinct()

# Renaming the columns

colnames(FMR_Nash) <- c("ZIP", "Studio", "BR1", "BR2", "BR3", "BR4")

# Averaging estimates

FMR_Nash <- FMR_Nash %>%
  mutate(ZIP_Average = (Studio + BR1 + BR2 + BR3 + BR4) / 5)

# Sorting in descending order by ZIP_Average

FMR_Nash <- FMR_Nash %>%
  arrange(desc(ZIP_Average))

# Showing the data as a table

FMR_Nash_table <- gt(FMR_Nash) %>%
  tab_header("Nashville FMR, by size and ZIP") %>%
  cols_align(align = "left") %>%
  gt_theme_538

FMR_Nash_table

# Averaging estimates

FMR_Nash <- FMR_Nash %>%
  mutate(ZIP_Average = (Studio + BR1 + BR2 + BR3 + BR4) / 5)

# Sorting in descending order by ZIP_Average

FMR_Nash <- FMR_Nash %>%
  arrange(desc(ZIP_Average))

# Showing the data as a table

FMR_Nash_table <- gt(FMR_Nash) %>%
  tab_header("Nashville FMR, by size and ZIP") %>%
  cols_align(align = "left") %>%
  gt_theme_538

FMR_Nash_table

#Map

# Downloading the ZIP code map file

download.file("https://www2.census.gov/geo/tiger/GENZ2020/shp/cb_2020_us_zcta520_500k.zip","ZCTAs2020.zip")

# Unzipping the ZIP code map file

unzip("ZCTAs2020.zip")

# Loading the ZIP code file into R as "ZCTAMap"

ZCTAMap <- read_sf("cb_2020_us_zcta520_500k.shp")

# Making ZIP a character variable

FMR_Nash$ZIP <- as.character(FMR_Nash$ZIP)

# Joining the files

FMR_Nash_Map <- left_join(FMR_Nash, ZCTAMap, by = c("ZIP" = "ZCTA5CE20"))

# Dropping unneeded columns 

FMR_Nash_Map <- FMR_Nash_Map %>%
  select(-c(AFFGEOID20, GEOID20, NAME20, LSAD20, ALAND20, AWATER20))

# Converting FMR_Nash_Map

FMR_Nash_Map <- st_as_sf(FMR_Nash_Map)

# Making the map

Rent_Category_Map <- mapview(
  FMR_Nash_Map,
  zcol = "ZIP_Average",
  col.regions = brewer.pal(9,"Blues"),
  layer.name = "Rent Average",
  popup = popupTable(
    FMR_Nash_Map,
    feature.id = FALSE,
    row.numbers = FALSE,
    zcol = c("ZIP", "Studio", "BR1", "BR2", "BR3", "BR4")))

# Showing the map

Rent_Category_Map

#API

census_api_key("93315bc9312a299da799361cc702a29db484d7cd")
Census_Data <- get_acs(
  geography = "zcta",
  variables = c("DP04_0047", "DP04_0045"),
  year = 2023,
  survey = "acs5",
  output = "wide",
  geometry = FALSE
)
Census_Data <- Census_Data %>% 
  rename(c("Rentals" = "DP04_0047E",
           "Rentals_MOE" = "DP04_0047M",
           "Households" = "DP04_0045E",
           "Households_MOE" = "DP04_0045M"))

glimpse(Census_Data)

# Merging Rent_Category_Map and Census_Data

FMR_Nash_Map <- left_join(FMR_Nash_Map, Census_Data, by = c("ZIP" = "GEOID"))

ZIP_Map <- mapview(
  FMR_Nash_Map,
  zcol = "ZIP_Average",
  col.regions = brewer.pal(9, "Blues"),
  layer.name = "Average rent",
  popup = popupTable(
    FMR_Nash_Map,
    feature.id = FALSE,
    row.numbers = FALSE,
    zcol = c("ZIP", "Studio", "BR1", "BR2", "BR3", "BR4",
             "Rentals", "Rentals_MOE", "Households", "Households_MOE")))

# Showing the map

ZIP_Map