How to use EJAM to analyze zip codes
EJAM can analyze various kinds of Census-defined areas, including States, Counties, Tracts, Blockgroups, and Cities/CDPs/etc.
However, you may need to analyze zip codes.
Census uses ZIP Code Tabulation Areas (ZCTAs), which are generalized
areal representations of United States Postal Service (USPS) ZIP Code
service areas. See help("zctas", package="tigris")
Note a zip can be the same as a county fips in many cases, as with 10001!

The original (pre-2025) EJSCREEN API did not handle zip codes. It can show where the center of the zip code is but will not map its bounds or provide a report easily via the API.
# Just see where the zipcode is, not its boundaries
# (use zip= , not wherestr= : a bare 5-digit wherestr is now read as a county FIPS first,
# so wherestr = '10001' would open Kent County, DE instead of this Manhattan zip code)
browseURL(url_ejscreenmap(zip = '10001'))To map and analyze zip codes you can download shapefiles for them and analyze or map them in EJAM as shown below.
downloading zcta polygons
Takes time to download!
library(tigris)
# options(tigris_use_cache=TRUE) # done by EJAM load/attach
options(tigris_refresh=FALSE)
#zcta_DE <- zctas(starts_with = fips_from_name('DE'), keep_zipped_shapefile = T) # all in the state
#zcta1 <- zctas(starts_with = c("10001")) # one zip
zcta2 <- zctas(starts_with = c("10012", "10506")) # two zipcodes
z = shapefile_from_any(zcta2)mapping zcta polygons
mapfast(z)Another source of zip code polygons (esri service)
# Download spatial bounds for all zipcodes in Delaware
ST1 <- "DE"
url1 <- paste0("https://services.arcgis.com/P3ePLMYs2RVChkJx/ArcGIS/rest/services/USA_Boundaries_2022/FeatureServer/3/query?",
"where=STATE%3D%27", ST1, "%27",
"&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&resultType=none&distance=0.0&units=esriSRUnit_Meter&relationParam=&returnGeodetic=false",
"&outFields=*",
"&returnGeometry=true",
"&f=json")
require(httr2); require(sf); require(mapview)
response1 <- httr2::req_perform(httr2::request(url1))
text1 <- httr2::resp_body_string(response1)
shp1 <- sf::st_read(text1)
mapview::mapview(shp1)see EJSCREEN map at a zip code
The EJScreen map app can be opened at zip code(s) via a deep link,
using its ?zip= launch-URL parameter – the explicit way to
pass a zip code. That matters because a bare 5-digit number is
ambiguous: 10001 is both a Manhattan zip code and Kent County, DE’s
county FIPS, and EJScreen deep links read a bare 5-digit
wherestr= as a county FIPS first (EJAM’s convention). The
zip argument of url_ejscreenmap() builds the
unambiguous zip links:
# one zip code: EJScreen opens centered there, with a pin and the site report popup
browseURL(url_ejscreenmap(zip = "20019"))
#> opens https://pedp-ejscreen.azurewebsites.net/index.html?zip=20019
# note the zip parameter, unlike wherestr, is never confused with a county FIPS:
url_ejscreenmap(zip = "10001") # zip 10001, in Manhattan, NY
url_ejscreenmap(fips = "10001") # county FIPS 10001 = Kent County, DE (boundary drawn)
# several zips in one link (the map zooms to fit all of them),
# and radius= prefills the report buffer distance in miles:
url_ejscreenmap(zip = c("20019", "20020"), combined = TRUE, radius = 1)
#> "https://pedp-ejscreen.azurewebsites.net/index.html?zip=20019,20020&radius=1"
# a zip passed as a number gets its leading zeroes restored:
url_ejscreenmap(zip = 1001) # zip 01001, Agawam, MAThese links need the EJScreen release that added deep links (see Public-Environmental-Data-Partners/EJScreen#70); the map pins the zip’s location – for analyzing the zip code’s actual boundaries, use the zcta polygons approach above.
analyzing zip codes in EJAM
You can analyze zip codes in EJAM like this:
out = ejamit(shapefile = z, radius = 0)summary report on zipcodes
ejam2report(out,
analysis_title = "Zip codes",
site_method = 'SHP',
shp = z)compare sites
# put zip code in the x axis labels!
ejam2barplot_sites(out, names.arg = z$GEOID20, sortby = FALSE) # zcta2$GEOID20
# This table view works, but the links to reports do not work with zipcodes
ejam2tableviewer(out)map of detailed results
out_plus_shape = sf::st_as_sf(
data.frame(out$results_bysite, z)
)
# put zip code in the map popups!
out_plus_shape$ejam_uniq_id = paste0(out_plus_shape$ejam_uniq_id, " (zip ", z$GEOID20, ")")
mapfastej(out_plus_shape)Note that ejam2map() will not work for zipcodes!