Here is the R code for mapping and tabulating Toxics Release Inventory data from the U.S. Environmental Protection Agency:

# ============================================================
#  TRI Data Analysis and Carcinogen Mapping for Tennessee (2023)
# ============================================================

# ------------------------------------------------------------
# 1. Install and load required packages
# ------------------------------------------------------------
if (!require("tidyverse")) install.packages("tidyverse")
if (!require("leaflet")) install.packages("leaflet")
if (!require("DT")) install.packages("DT")

library(tidyverse)
library(leaflet)
library(DT)

# ------------------------------------------------------------
# 2. Download and load EPA TRI dataset (2023 Tennessee)
# ------------------------------------------------------------
tri <- read.csv(
  "https://data.epa.gov/efservice/downloads/tri/mv_tri_basic_download/2023_TN/csv",
  as.is = TRUE
)

# ------------------------------------------------------------
# 3. Clean column names for clarity
# ------------------------------------------------------------
names(tri) <- gsub("X\\d+\\.\\.", "", names(tri))
names(tri) <- gsub("[0-9\\d\\.ABCD]+\\.\\.\\.", "", names(tri))

# ------------------------------------------------------------
# 4. Select relevant columns
# ------------------------------------------------------------
tri <- subset(
  tri,
  select = c(
    FACILITY.NAME,
    CITY,
    LATITUDE,
    LONGITUDE,
    CHEMICAL,
    CARCINOGEN,
    FUGITIVE.AIR,
    STACK.AIR,
    WATER,
    UNIT.OF.MEASURE
  )
)

options(scipen = 999)  # disable scientific notation

# ------------------------------------------------------------
# 5. Convert grams to pounds (where applicable)
# ------------------------------------------------------------
multiplier <- ifelse(tri$UNIT.OF.MEASURE == "Grams", 1 / 453.592, 1)
tri$FUGITIVE.AIR <- multiplier * tri$FUGITIVE.AIR
tri$STACK.AIR <- multiplier * tri$STACK.AIR
tri$WATER <- multiplier * tri$WATER
tri$UNIT.OF.MEASURE <- "Pounds"

# ------------------------------------------------------------
# 6. Handle missing values and compute totals
# ------------------------------------------------------------
tri$FUGITIVE.AIR[is.na(tri$FUGITIVE.AIR)] <- 0
tri$STACK.AIR[is.na(tri$STACK.AIR)] <- 0
tri$WATER[is.na(tri$WATER)] <- 0

tri$TOTAL.POUNDS <- tri$FUGITIVE.AIR + tri$STACK.AIR + tri$WATER
tri$CARCINOGEN.POUNDS <- ifelse(tri$CARCINOGEN == "YES", tri$TOTAL.POUNDS, 0)

# ------------------------------------------------------------
# 7. Filter data to include carcinogenic releases only
# ------------------------------------------------------------
data <- tri %>% filter(CARCINOGEN.POUNDS > 0)
data$LATITUDE <- as.numeric(data$LATITUDE)
data$LONGITUDE <- as.numeric(data$LONGITUDE)

# ------------------------------------------------------------
# 8. Create interactive summary table of carcinogen totals
# ------------------------------------------------------------
summary_table <- data %>%
  group_by(CITY, CHEMICAL) %>%
  summarize(
    Facilities = n_distinct(FACILITY.NAME),
    Total_Pounds = round(sum(CARCINOGEN.POUNDS, na.rm = TRUE), 2)
  ) %>%
  arrange(desc(Total_Pounds))

datatable(
  summary_table,
  options = list(pageLength = 10, scrollX = TRUE),
  caption = "Summary of Carcinogenic Chemical Releases by City (2023)"
)

# ------------------------------------------------------------
# 9. Create popup text for interactive map
# ------------------------------------------------------------
data$popup <- paste0(
  "<b>Facility name: </b>", data$FACILITY.NAME,
  "<br><b>City: </b>", data$CITY,
  "<br><b>Carcinogen: </b>", data$CHEMICAL,
  "<br><b>Fugitive air: </b>", round(data$FUGITIVE.AIR, 2), " lbs",
  "<br><b>Stack air: </b>", round(data$STACK.AIR, 2), " lbs",
  "<br><b>Water: </b>", round(data$WATER, 2), " lbs",
  "<br><b>Total pounds: </b>", round(data$CARCINOGEN.POUNDS, 2)
)

# ------------------------------------------------------------
# 10. Create interactive map of carcinogenic emissions
# ------------------------------------------------------------
TheMap <- leaflet(data, width = "100%") %>%
  addTiles(group = "OSM (default)") %>%
  addProviderTiles("Esri.WorldStreetMap", group = "World StreetMap") %>%
  addProviderTiles("Esri.WorldImagery", group = "World Imagery") %>%
  addMarkers(
    lng = ~LONGITUDE,
    lat = ~LATITUDE,
    popup = ~popup,
    clusterOptions = markerClusterOptions()
  ) %>%
  addLayersControl(
    baseGroups = c("OSM (default)", "World StreetMap", "World Imagery"),
    options = layersControlOptions(collapsed = FALSE)
  )

TheMap