Introduction

Environmental justice mapping can be easily done with the EPA’s free EJSCREEN tool (https://ejscreen.epa.gov/mapper/). This mapping tool provides a great introduction to analyzing and comparing environmental justice issues. However, this mapping tool would not suffice for a three hour upperclassman college lab.

In addition, the Department of Environmental Conservation (DEC) provides a free interactive map called the DECinfo Locator (https://gisservices.dec.ny.gov/gis/dil/). One layer of this map allows users view DEC sites across New York State. This allows easy viewing of DEC site locations as well as information about these sites.

Learning how to map is a useful skill. Introducing students how to map in RStudio is also especially beneficial. The overall goal is to develop a step-by-step lab for students to create environmental justice maps in RStudio that are similar to EJSCREEN and the DECinfo Locator. In addition, teaching students how to create static and interactive tables will allow students to learn various ways to create tables in RStudio. The end product of these maps and tables will thus be presented in this project.

Low-income and race are key indicators to observe when analyzing environmental injustice. In the context of Western New York, I want the students to analyze how marginalized communities have been impacted unequally compared to higher-income and white neighborhoods. Exploration and comparison of environmental injustice will help students understand the core inequality issues in Western New York. Therefore, I hypothesize that the lower-income and black neighborhoods will live closer to sites that have been or are in the process of being remediated. Despite the fact that some sites will be remediated already, this is still an indicator that the site was once contaminated, so it historically shows contamination that marginalized communities have lived near.

Materials and Methods

Packages

library(tidycensus)
library(tidyverse)
library(tigris)
library(sf)
library(sp)
library(leaflet)
library(RColorBrewer)
library(scales)
library(kableExtra)
library(dplyr)
library(DT)

Accessing ACS Data

The tidycensus package (Walker and Herman n.d., n.d., Walker et al. 2020) allows users to easily gather decennial United States Census data and American Community Survey (ACS) data as well as the United States Census Bureau’s geographic boundary files. Gathering Census data can be difficult, so this package is an easy-to-use tool to quickly gather data. I have chosen to work with the ACS 5-year estimates since this is best used with data at the census tract level or smaller (United States Census Bureau 2020). Since I will be looking at the census tract level for demographic data, the ACS 5-year estimates data was the best option. A lot of the code I used to sort through this data was what I learned from the DataCamp course on the tidycensus package (Walker et al. n.d.).

loadacs5 <- load_variables(2018, "acs5", cache = TRUE)
#api_key <- census_api_key("type_your_API_key_here")
# Request an API key from here https://api.census.gov/data/key_signup.html

tract_income <- get_acs(geography = "tract", variables = "B19125_001", state = "NY", 
                        county = c("Erie", "Niagara", "Cattaraugus"), 
                        year = 2018, geometry = TRUE)
#head(tract_income)
st_tract_income <- tract_income %>%
  st_transform("+proj=longlat +datum=WGS84") #transforming coordinates of tract_income to a new projection

tract_race <- get_acs(geography = "tract", variables = "B02001_003", state = "NY",
                      county = c("Erie", "Niagara", "Cattaraugus"), 
                      year = 2018, geometry = TRUE)
#head(tract_race)
st_tract_race <- tract_race %>%
  st_transform("+proj=longlat +datum=WGS84") #transforming coordinates of tract_race to a new projection

Gathering and Tidying the DEC Data

The New York State Department of Environmental Conservation (2020) has a free database of remediation site records that is updated daily. To sort through my data, I had to filter two types of rows within one column (Nishida 2016). Lastly, there was duplicated data in this database, so I used directions from Datanovia (n.d.).

Site Classifications That I Have Filtered For

  • Numbered sites are listed on the “Registry of Inactive Hazardous Waste Disposal Sites” (called “Registry” sites).
  • Lettered sites are Non-Registry sites that are/have been investigated and remediated through a brownfield program or another environmental remediation program.
Site Class Description
02 Disposal of hazardous waste represents a significant threat to the environment or to health, or hazardous waste disposal has not been confirmed, but the site has been listed on the Federal National Priorities List.
04 The site has been properly closed but still requires continued site management consisting of operation, maintenance and/or monitoring.
05 The site has been properly closed and requires no continued management.
A The site is actively being remediated and the remedial program is not yet complete.
C Remediation has been satisfactorily completed.

(Department of Environmental Conservation n.d.)

DEC_data <- read.csv("https://data.ny.gov/api/views/c6ci-rzpg/rows.csv?accessType=DOWNLOAD&bom=true&format=true&sorting=true")
#View(DEC_data)

DEC_data_unique <- DEC_data %>%
  distinct(Program.Type, Program.Facility.Name, Site.Class, Address1, Locality, County, 
           ZIPCode, SWIS.Code, DEC.Region, Latitude, Longitude, Georeference, 
           .keep_all = TRUE)
#View(DEC_data_unique)

hazardous_sites <- DEC_data_unique %>%
  filter(Site.Class %in% c("02", "A") & County %in% c("Erie", "Niagara", "Cattaraugus"))
hazardous_sites_sf <- st_as_sf(hazardous_sites, 
                               coords = c("Longitude", "Latitude"), 
                               dim = "XY")

remediated_sites <- DEC_data_unique %>%
  filter(Site.Class %in% c("04", "05", "C") & County %in% c("Erie", "Niagara", "Cattaraugus"))
remediated_sites_sf <- st_as_sf(remediated_sites, 
                                coords = c("Longitude", "Latitude"), 
                                dim = "XY")

Results

Finding the Number of Tracts Where a Race or Ethnicity is the Majority for that Tract

I was inspired by the tidycensus course from Walker et al. (n.d.) to create a table that showed the number of tracts that a certain race or ethnicity is the majority for that tract. I created this table from Hao (2020).

race_eth <- c(White = "B03002_003", Black = "B03002_004", Indigenous = "B03002_005",
          Asian = "B03002_006", Hispanic =  "B03002_012")
race_eth_acs <- get_acs(geography = "tract", state = "NY",
                      county = c("Erie", "Niagara", "Cattaraugus"), variables = race_eth,
                      summary_var = "B03002_001",
                      year = 2018, geometry = TRUE)
#head(race_eth_acs)

race_eth_lgst <- race_eth_acs %>%
  group_by(GEOID) %>%
  filter(estimate == max(estimate)) %>%
  select(NAME, variable, estimate) %>%
  st_set_geometry(NULL)

race_eth_summarize <- race_eth_lgst %>%
  group_by(variable) %>%
  tally() %>%
  rename(c("Race/Ethnicity" = variable, "Number of Tracts" = n))

kable(race_eth_summarize) %>%
  kable_styling(bootstrap_options = "striped", full_width = F, position = "left")
Race/Ethnicity Number of Tracts
Asian 6
Black 42
Hispanic 10
Indigenous 8
White 274

Creating an Interactive Table

As opposed to a static table, the students can explore this interactive table to observe the DEC sites in Western New York in a clean format through the DT package (RStudio GitHub n.d.).

wny_sites <- DEC_data_unique %>%
  filter(Site.Class %in% c("02", "04", "05", "A", "C") & 
           County %in% c("Erie", "Niagara", "Cattaraugus")) %>%
  select(Program.Number, Program.Type, Program.Facility.Name, Site.Class, Address1,
         Locality, County, ZIPCode)
#View(wny_sites)

datatable(wny_sites, options = list(), class = "cell-border stripe", 
          colnames = c("Program Number", "Program Type", "Facility Name", "Site Class",
                       "Address", "City/Town/Village", "County", "Zip Code"), 
          rownames = FALSE)

Mapping Demographic Data

I chose to map the median household income estimate in the past 12 months on one layer and the total black population estimate on another layer for Erie, Niagara, and Cattaraugus Counties. The median household income data provided the best visual representation of the income inequalities throughout Western New York. Also, I chose to map only the black population simply due to time constraints. I learned how to create these maps from DataCamp’s course on the leaflet package (Majerus n.d.), and from other sources (GitHub n.d., Holtz n.d., RStudio GitHub n.d., Silge 2017).

income_pal <- colorBin(palette = "Greens", bins = 9, domain = st_tract_income$estimate)
race_pal <- colorBin(palette = "RdPu", bins = 9, pretty = FALSE,
                     domain = st_tract_race$estimate)

demographics_map <- leaflet() %>%
  setView(lng = -78.878738, lat = 42.880230, zoom = 7) %>%
  setMaxBounds(lng1 = -71.254028, lat1 = 46.829853, lng2 = -84.512016, lat2 = 39.103119) %>%
  addProviderTiles("Esri", options = providerTileOptions(minZoom = 5)) %>% 
  addPolygons(data = st_tract_income, 
              weight = 2,
              fillOpacity = 0.8, 
              color = ~ income_pal(estimate), 
              label = ~paste0("Estimate Household Income: ", dollar(estimate)),
              highlight = highlightOptions(weight = 2, 
                                           color = "black", bringToFront = TRUE),
              group = "Income") %>%
  addLegend(position = "bottomleft", 
            pal = income_pal, 
            values = st_tract_income$estimate,
            title = "Median Household Income", opacity = 0.7,
            labFormat = labelFormat(prefix = "$")) %>%
  addPolygons(data = st_tract_race, 
              weight = 2,
              fillOpacity = 0.9, 
              color = ~ race_pal(estimate), 
              label = ~paste0("Estimate Population: ", estimate),
              highlight = highlightOptions(weight = 2, 
                                           color = "black", bringToFront = TRUE),
              group = "Race") %>%
  addLegend(position = "bottomright", 
            pal = race_pal, 
            values = st_tract_race$estimate,
            title = "Black Population", 
            opacity = 0.7, 
            labFormat = labelFormat(digits = 0)) %>%
  addLayersControl(overlayGroups = c("Income", "Race"))

demographics_map

Mapping DEC Sites

I have mapped the DEC sites that are in the process of being remediated on one layer and the DEC sites that have been remediated (but may still be monitored) on another layer for Erie, Niagara, and Cattaraugus Counties. I used the knowledge I gained from the demographic maps I made to create this map. I also learned how to use line breaks in my legend from the DataCamp course on leaflet (Majerus n.d.).

dec_map <- leaflet() %>%
  setView(lng = -78.878738, lat = 42.880230, zoom = 7) %>%
  setMaxBounds(lng1 = -71.254028, lat1 = 46.829853, lng2 = -84.512016, lat2 = 39.103119) %>%
  addProviderTiles("Esri", options = providerTileOptions(minZoom = 5)) %>%
  addCircleMarkers(data = hazardous_sites_sf, 
                   radius = 1.3, 
                   color = "red", 
                   opacity = .7,
                   popup = ~paste0("<b>", "Site Name: ", Program.Facility.Name, "</b>", 
                         "<br/>", "Address: ", Address1,
                         "<br/>", "Site Class: ", Site.Class),
                   group = "Hazardous Sites") %>%
  addCircleMarkers(data = remediated_sites_sf, 
                   radius = 1.3, 
                   color = "purple", 
                   opacity = .7,
                   popup = ~paste0("<b>", "Site Name: ", Program.Facility.Name, "</b>", 
                         "<br/>", "Address: ", Address1,
                         "<br/>", "Site Class: ", Site.Class),
                   group = "Remediated Sites") %>%
  addLayersControl(overlayGroups = c("Hazardous Sites", "Remediated Sites"))

dec_map

Conclusions

I can conclude that low-income and black communities live closest to sites that are in the process of or have been remediated. The clustering of DEC sites in census tracts with the lowest income and higher black populations displays a prime example of environmental injustice occurring in Western New York. I can also conclude that 42 tracts in Erie, Niagara, and Cattaraugus Counties have black as the majority race. Lastly, using the DT package is an efficient way to allow students to create interactive tables to explore DEC sites.

In the future, it would be useful to map Asian, Hispanic, and Indigenous populations to observe the possible environmental injustices they face. Will evidence of environmental injustice be as clear as what black communities face? Also, mapping other environmental hazards, such as proximity to major intersections, lead paint exposure, and particulate matter 2.5 exposure, will allow for future analysis of the extent of environmental hazards that marginalized communities face. With the completion of this script, the next course of action is to create steps for college students to follow in their environmental injustice mapping lab.

Overall, introducing college students to environmental justice issues and interactive mapping will hopefully inspire at least one student to want to fight environmental justice in one way or another, such as through interactive maps.

References

Datanovia. (n.d.). Identify and Remove Duplicate Data in R. https://www.datanovia.com/en/lessons/identify-and-remove-duplicate-data-in-r/.

Department of Environmental Conservation. (n.d.). Site Classifications. https://www.dec.ny.gov/chemical/8663.html.

GitHub. (n.d.). addLegend and NA work but only with a workaround · Issue #485. https://github.com/rstudio/leaflet/issues/485.

Hao, Z. 2020, October 22. Create Awesome HTML Table with knitr::kable and kableExtra. https://cran.r-project.org/web/packages/kableExtra/vignettes/awesome_table_in_html.html.

Holtz, Y. (n.d.). R Color Brewer’s palettes. https://www.r-graph-gallery.com/38-rcolorbrewers-palettes.html.

Majerus, R. (n.d.). Interactive Maps with leaflet in R. https://learn.datacamp.com/courses/interactive-maps-with-leaflet-in-r.

New York State Department of Environmental Conservation. 2020. Environmental Remediation Sites. https://data.ny.gov/Energy-Environment/Environmental-Remediation-Sites/c6ci-rzpg.

Nishida, K. 2016, March 11. Filtering Data with dplyr. https://blog.exploratory.io/filter-data-with-dplyr-76cf5f1a258e.

RStudio GitHub. (n.d.). Leaflet for R - Legends. https://rstudio.github.io/leaflet/legends.html.

RStudio GitHub. (n.d.). DT: An R interface to the DataTables library. https://rstudio.github.io/DT/.

Silge, J. 2017, June 24. Using tidycensus and leaflet to map Census data. https://juliasilge.com/blog/using-tidycensus/.

United States Census Bureau. 2020, September 10. When to Use 1-year, 3-year, or 5-year Estimates. https://www.census.gov/programs-surveys/acs/guidance/estimates.html.

Walker, K., and M. Herman. (n.d.). Basic usage of tidycensus. https://walker-data.com/tidycensus/articles/basic-usage.html.

Walker, K., and M. Herman. (n.d.). Spatial data in tidycensus. https://walker-data.com/tidycensus/articles/spatial-data.html.

Walker, K., M. Herman, and K. Eberwein. 2020, September 28. Package “tidycensus.”

Walker, K., C. Ismay, and R. Robins. (n.d.). Analyzing US Census Data in R. https://learn.datacamp.com/courses/analyzing-us-census-data-in-r.