Introduction to echor

Michael Schramm

2019-09-17

echor introduction

echor is an R package to search and download data from the US Environmental Protection Agency (EPA) Environmental Compliance and History Online (ECHO). echor uses the ECHO API to download data directly to the R as dataframes or simple features. ECHO provides information about facilities permitted to emitted air pollutants or discharge into water bodies. ECHO also provides data reported by permitted facilites as volume or concentration of pollutants during reporting time periods (typically anually for air emissions and monthly or quarterly for water discharges).

ECHO provides data for:

echor currently provides functions to retrieve information about permitted air dischargers, water dischargers, and public drinking water supply systems. It also provides functions to download discharge reports for permitted air and water dischargers. echor does not currently provide functionality to retrieve RCRA data.

See https://echo.epa.gov/tools/web-services for information about ECHO web services and API functions.

Getting started

This vignette documents a few key functions to get started.

There are three types of functions:

Metadata

Retrieve metadata from ECHO to narrow the specify data returned or lookup parameter codes.

Query Facilities

Search and return facility information based on lookup parameters.

Reports

Search and return discharge and emissions reports for specified facilities.

Sample workflows

Air

Suppose we want to find facilities permitted under the Clean Air Act requirements.

Step 1 - Identify the information we need returned from the query:

The dataframe includes ColumnID, which can be included as an argument that specifies what information you want returned: qcolumns = "1,2,3,22,23"

Step 2 - Create the query. The ECHO API provides numerous arguments to search by that are not documented in this package. I reccomend exploring the documentation here: https://echo.epa.gov/tools/web-services/facility-search-air#!/Facilities/get_air_rest_services_get_facility_info. In this example, we will search by a geographic bounding box and specfiy the returned information with the qcolumns argument. Each argument should be passeed to ECHO as echoAirGetFacilityInfo(parameter = "value"). echor will URL encode strings automatically. Please note that any date argument needs to be entered as “mm/dd/yyyy”.

AIRName SourceID AIRStreet FacLat FacLong
AGGIE CLEANERS 06000000480416E020 111 COLLEGE MAIN 30.61869 -96.34588
ALL SEASONS 1 HR CLEANERS 06000000480416E015 2501 TEXAS AVENUE SOUTH #D100 30.60704 -96.30875
BLUEBONNET PAVING TX0000004877700147 HWY. 60, WEST OF 30.61337 -96.32098
BRAZOS PAVING TRENCH BURNER IN1633 TX0000004877702288 TURN S ON VICTORIA AVE OFF OF HWY 40 TAKE A R ON W 30.61337 -96.32098
BRYAN CERAMICS PLANT TX0000004804100027 1500 INDEPENDENCE AVE 30.63760 -96.36235
BRYAN CLEANERS & LAUNDRY 06000000480416E012 1803 HOLLEMAN DRIVE 30.61225 -96.31750

Some example arguments are listed below:

p_fn  string  Facility Name Filter.
              One or more case-insesitive facility names.
              Provide multiple values as comma-delimited list
              ex:
              p_fn = "Aggie Cleaners, City of Bryan, TEXAS A&M UNIVERSITY COLLEGE STATION CAMPUS"
              
p_sa  string  Facility Street Address
              ex:
              p_sa = "WELLBORN ROAD & UNIVERSITY DR"
              
p_ct  string  Facility City
              Provide a single case-insensitive city name
              ex:
              p_ct = "College Station"
              
p_co  string  Facility County
              Provide a single county name, in combination with a state value
              provided through p_st
              ex:
              p_co = "Brazos", p_st = "Texas"
              
p_fips  string  FIPS Code
                Single 5-character Federal Information Processing Standards (FIPS) 
                state+county value
                
p_st  string  Facility State or State Equivalent Filter
              Provide one or more USPS postal abbreviations
              ex:
              p_st = "TX, NC"
              
p_zip string  Facility 5-Digit Zip Code
              Provide one or more 5-digit postal zip codes
              ex:
              p_zip = "77843, 77845"
              
xmin  string  Minimum longitude value in decimal degrees

ymin  string  Minimum latitude value in decimal degrees

xmax  string  Maximum longitude value in decimal degrees

ymax  string  Maximum latitude value in decimal degrees

Step 3 - Download the emission inventory report for a permitted facility:

Name SourceID Street City State Zip County Region Latitude Longitude Pollutant UnitsOfMeasure Program Year Discharge
CP&L - SUTTON PLANT 110000350174 801 SUTTON STEAM PLANT ROAD WILMINGTON NC 28401 NEW HANOVER 04 34.28332 -77.98523 1,2-Dichloroethane Pounds NEI 2008 47.95
CP&L - SUTTON PLANT 110000350174 801 SUTTON STEAM PLANT ROAD WILMINGTON NC 28401 NEW HANOVER 04 34.28332 -77.98523 Acetophenone Pounds NEI 2008 17.98
CP&L - SUTTON PLANT 110000350174 801 SUTTON STEAM PLANT ROAD WILMINGTON NC 28401 NEW HANOVER 04 34.28332 -77.98523 Anthracene Pounds NEI 2008 0.25
CP&L - SUTTON PLANT 110000350174 801 SUTTON STEAM PLANT ROAD WILMINGTON NC 28401 NEW HANOVER 04 34.28332 -77.98523 Dimethyl sulfate Pounds NEI 2008 63.19
CP&L - SUTTON PLANT 110000350174 801 SUTTON STEAM PLANT ROAD WILMINGTON NC 28401 NEW HANOVER 04 34.28332 -77.98523 Hexane Pounds NEI 2008 80.31
CP&L - SUTTON PLANT 110000350174 801 SUTTON STEAM PLANT ROAD WILMINGTON NC 28401 NEW HANOVER 04 34.28332 -77.98523 Manganese Pounds NEI 2008 290.51

There are only two valid arguments for echoGetCAAPR.

p_id  string  EPA Facility Registry Service's REGISTRY_ID.

p_units string  Units of measurement. Defaults is 'lbs'.
                Enter "TPWE" for toxic weighted pounds equivalents.

Water facility and discharge searches

Find facilites with NPDES permits to discharge wastewater:

CWPName SourceID CWPStreet CWPCity CWPState CWPStateDistrict CWPZip MasterExternalPermitNmbr RegistryID CWPCounty CWPEPARegion FacDerivedHuc FacLat FacLong CWPTotalDesignFlowNmbr CWPActualAverageFlowNmbr ReceivingMs4Name AssociatedPollutant MsgpPermitType CWPPermitStatusDesc CWPPermitTypeDesc CWPIssueDate CWPEffectiveDate CWPExpirationDate CWPSNCStatusDate CWPStateWaterBodyCode
ACE TOWNHOME TXR15667I 2136 CHESTNUT OAK CIR COLLEGE STATION TX 77845-4168 TXR150000 110070364352 06 12070103 30.61411 -96.28490 NA NA Effective General Permit Covered Facility 2018-06-01 2018-06-01 2023-03-05 2018-09-30
AGGIE ACRES WWTP TX0132187 800 FT SE OF N DOWLING RD APPROX 600 FT SW OF WALN COLLEGE STATION TX 77845 110064633829 Brazos 06 30.55565 -96.29110 NA NA Not Needed NPDES Individual Permit NA NA NA 2018-09-30
AGRIVEST SWINE FEEDLOT TX0121240 SWISHER COUNTY BRYAN TX 00000 110039193271 Swisher 06 30.66658 -96.36552 NA NA Terminated NPDES Individual Permit 2000-01-14 2000-01-14 2004-07-27 2018-09-30
ALENCO WINDOWS TXR05U808 615 W CARSON ST BRYAN TX 77801-1102 TXR050000 110000464284 Brazos 06 12070103 30.64457 -96.37270 NA NA Effective General Permit Covered Facility 2016-10-28 2016-11-01 2021-08-13 2018-09-30
ANDREWS ORTHODONTIST AND RETAIL BUILDING TXR15193R 1098 ARRINGTON RD COLLEGE STATION TX 77845 TXR150000 110070368658 06 12070103 30.55800 -96.26566 NA NA Effective General Permit Covered Facility 2018-08-27 2018-09-01 2023-03-05 2018-09-30
ASTIN AVIATION TXR05CE76 1770 GEORGE BUSH DR W COLLEGE STATION TX 77845-4761 TXR050000 110070360445 06 12070101 30.59288 -96.35277 NA NA Effective General Permit Covered Facility 2017-07-10 2017-08-01 2021-08-13 2018-09-30

Again, there are a ton of possible arguments to query ECHO with. All arguments are described here: https://echo.epa.gov/tools/web-services/facility-search-water#!/Facility_Information/get_cwa_rest_services_get_facility_info

Commonly used arguments are provided below:

p_fn  string  Facility Name Filter.
              One or more case-insesitive facility names.
              Provide multiple values as comma-delimited list
              ex:
              p_fn = "Aggie Cleaners, City of Bryan, TEXAS A&M UNIVERSITY COLLEGE STATION CAMPUS"
              
p_sa  string  Facility Street Address
              ex:
              p_sa = "WELLBORN ROAD & UNIVERSITY DR"
              
p_ct  string  Facility City
              Provide a single case-insensitive city name
              ex:
              p_ct = "College Station"
              
p_co  string  Facility County
              Provide a single county name, in combination with a state value
              provided through p_st
              ex:
              p_co = "Brazos", p_st = "Texas"
              
p_fips  string  FIPS Code
                Single 5-character Federal Information Processing Standards (FIPS) 
                state+county value
                
p_st  string  Facility State or State Equivalent Filter
              Provide one or more USPS postal abbreviations
              ex:
              p_st = "TX, NC"
              
p_zip string  Facility 5-Digit Zip Code
              Provide one or more 5-digit postal zip codes
              ex:
              p_zip = "77843, 77845"
              
xmin  string  Minimum longitude value in decimal degrees

ymin  string  Minimum latitude value in decimal degrees

xmax  string  Maximum longitude value in decimal degrees

ymax  string  Maximum latitude value in decimal degrees

p_huc string  2-,4,6-,or 8-digit watershed code.
              May contain comma-seperated values
              

Download discharge monitoring reports from ECHO from specified facilities:

activity_id npdes_id version_nmbr perm_feature_id perm_feature_nmbr perm_feature_type_code perm_feature_type_desc limit_set_id limit_set_schedule_id limit_id limit_type_code limit_begin_date limit_end_date nmbr_of_submission parameter_code parameter_desc monitoring_location_code monitoring_location_desc stay_type_code stay_type_desc limit_value_id limit_value_type_code limit_value_type_desc limit_value_nmbr limit_unit_code limit_unit_desc standard_unit_code standard_unit_desc limit_value_standard_units statistical_base_code statistical_base_short_desc statistical_base_type_code statistical_base_type_desc limit_value_qualifier_code stay_value_nmbr dmr_event_id monitoring_period_end_date dmr_form_value_id value_type_code value_type_desc dmr_value_id dmr_value_nmbr dmr_unit_code dmr_unit_desc dmr_value_standard_units dmr_value_qualifier_code value_received_date days_late nodi_code nodi_desc exceedence_pct npdes_violation_id violation_code violation_desc rnc_detection_code rnc_detection_desc rnc_detection_date rnc_resolution_code rnc_resolution_desc rnc_resolution_date violation_severity
NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA

This function only retrieves from a single facility per call. The following arguments are available from ECHO:

p_id  string  EPA Facility Registry Service's REGISTRY_ID.

outfall string  Three-character code identifying the point of discharge.

parameter_code  string  Five-digit numeric code identifying the parameter.

start_date  string  Start date of interest. Must be entered as "mm/dd/yyyy"

end_date  string  End date of interest. Must be entered as "mm/dd/yyyy"

Parameters codes can be searched using echoWaterGetParams.

Available arguments include:

term string partial or complete search phrase or word

code  string  partial or complete code value

You can only enter either term or code arguments.

Multiple DMRs can be downloaded using a helper function: downloadDMRs:

df <- tibble::tibble(permit = c('TX0119407', 'TX040237'))
df <- downloadDMRs(df, idColumn = permit)
#> Warning: 1762 parsing failures.
#> row col   expected    actual         file
#>   1  -- 61 columns 1 columns <raw vector>
#>   2  -- 61 columns 1 columns <raw vector>
#>   4  -- 61 columns 1 columns <raw vector>
#>   5  -- 61 columns 1 columns <raw vector>
#>   7  -- 61 columns 1 columns <raw vector>
#> ... ... .......... ......... ............
#> See problems(...) for more details.
#> Warning: 2 parsing failures.
#> row col   expected    actual         file
#>   1  -- 61 columns 1 columns <raw vector>
#>   2  -- 61 columns 1 columns <raw vector>
df <- df %>%
  tidyr::unnest(dmr)
tibble::glimpse(df)
#> Observations: 2,644
#> Variables: 62
#> $ permit                      <chr> "TX0119407", "TX0119407", "TX01194...
#> $ activity_id                 <chr> "", "", "3600178396", "", "", "360...
#> $ npdes_id                    <chr> NA, NA, "TX0119407", NA, NA, "TX01...
#> $ version_nmbr                <chr> NA, NA, "0", NA, NA, "0", NA, NA, ...
#> $ perm_feature_id             <chr> NA, NA, "3600049681", NA, NA, "360...
#> $ perm_feature_nmbr           <chr> NA, NA, "001", NA, NA, "001", NA, ...
#> $ perm_feature_type_code      <chr> NA, NA, "EXO", NA, NA, "EXO", NA, ...
#> $ perm_feature_type_desc      <chr> NA, NA, "External Outfall", NA, NA...
#> $ limit_set_id                <chr> NA, NA, "3600061722", NA, NA, "360...
#> $ limit_set_schedule_id       <chr> NA, NA, "3600073706", NA, NA, "360...
#> $ limit_id                    <chr> NA, NA, "3600437315", NA, NA, "360...
#> $ limit_type_code             <chr> NA, NA, "ENF", NA, NA, "ENF", NA, ...
#> $ limit_begin_date            <chr> NA, NA, "08/01/2015", NA, NA, "08/...
#> $ limit_end_date              <chr> NA, NA, "03/01/2020", NA, NA, "03/...
#> $ nmbr_of_submission          <chr> NA, NA, "1", NA, NA, "1", NA, NA, ...
#> $ parameter_code              <chr> NA, NA, "00300", NA, NA, "00300", ...
#> $ parameter_desc              <chr> NA, NA, "Oxygen, dissolved [DO]", ...
#> $ monitoring_location_code    <chr> NA, NA, "1", NA, NA, "1", NA, NA, ...
#> $ monitoring_location_desc    <chr> NA, NA, "Effluent Gross", NA, NA, ...
#> $ stay_type_code              <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ stay_type_desc              <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ limit_value_id              <chr> NA, NA, "3600678121", NA, NA, "360...
#> $ limit_value_type_code       <chr> NA, NA, "C1", NA, NA, "C1", NA, NA...
#> $ limit_value_type_desc       <chr> NA, NA, "Concentration1", NA, NA, ...
#> $ limit_value_nmbr            <chr> NA, NA, "4", NA, NA, "4", NA, NA, ...
#> $ limit_unit_code             <chr> NA, NA, "19", NA, NA, "19", NA, NA...
#> $ limit_unit_desc             <chr> NA, NA, "mg/L", NA, NA, "mg/L", NA...
#> $ standard_unit_code          <chr> NA, NA, "19", NA, NA, "19", NA, NA...
#> $ standard_unit_desc          <chr> NA, NA, "mg/L", NA, NA, "mg/L", NA...
#> $ limit_value_standard_units  <chr> NA, NA, "4", NA, NA, "4", NA, NA, ...
#> $ statistical_base_code       <chr> NA, NA, "MO", NA, NA, "MO", NA, NA...
#> $ statistical_base_short_desc <chr> NA, NA, "MO MIN", NA, NA, "MO MIN"...
#> $ statistical_base_type_code  <chr> NA, NA, "MIN", NA, NA, "MIN", NA, ...
#> $ statistical_base_type_desc  <chr> NA, NA, "Minimum", NA, NA, "Minimu...
#> $ limit_value_qualifier_code  <chr> NA, NA, ">=", NA, NA, ">=", NA, NA...
#> $ stay_value_nmbr             <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ dmr_event_id                <chr> NA, NA, "3403423185", NA, NA, "340...
#> $ monitoring_period_end_date  <chr> NA, NA, "10/31/2015", NA, NA, "11/...
#> $ dmr_form_value_id           <chr> NA, NA, "3442281413", NA, NA, "344...
#> $ value_type_code             <chr> NA, NA, "C1", NA, NA, "C1", NA, NA...
#> $ value_type_desc             <chr> NA, NA, "Concentration1", NA, NA, ...
#> $ dmr_value_id                <chr> NA, NA, "3614856990", NA, NA, "361...
#> $ dmr_value_nmbr              <chr> NA, NA, "5.21", NA, NA, "7.9", NA,...
#> $ dmr_unit_code               <chr> NA, NA, "19", NA, NA, "19", NA, NA...
#> $ dmr_unit_desc               <chr> NA, NA, "mg/L", NA, NA, "mg/L", NA...
#> $ dmr_value_standard_units    <chr> NA, NA, "5.21", NA, NA, "7.9", NA,...
#> $ dmr_value_qualifier_code    <chr> NA, NA, "=", NA, NA, "=", NA, NA, ...
#> $ value_received_date         <chr> NA, NA, "11/20/2015", NA, NA, "12/...
#> $ days_late                   <chr> NA, NA, "", NA, NA, "9", NA, NA, "...
#> $ nodi_code                   <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ nodi_desc                   <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ exceedence_pct              <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ npdes_violation_id          <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ violation_code              <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ violation_desc              <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ rnc_detection_code          <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ rnc_detection_desc          <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ rnc_detection_date          <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ rnc_resolution_code         <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ rnc_resolution_desc         <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ rnc_resolution_date         <chr> NA, NA, "", NA, NA, "", NA, NA, ""...
#> $ violation_severity          <chr> NA, NA, "0", NA, NA, "0", NA, NA, ...

Spatial data

echor can also return spatial data frames known as simple features (https://r-spatial.github.io/sf/), to facilitate creation of maps. Both echoAirGetFacilityInfo and echoWaterGetFacilityInfo include arguments to return simple feature dataframes.

Using sf, ggmap, and the current development version of ggplot2 (devtools::install_github("tidyverse/ggplot2")), we can quickly create a map of downloaded data.