# Introduction to echor

#### Michael Schramm

#### 2020-01-29

## 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 facilities as volume or concentration of pollutants during reporting time periods (typically annually for air emissions and monthly or quarterly for water discharges).

ECHO provides data for:

- Stationary sources permitted under the Clean Air Act, including data from the National Emissions Inventory, Greenhouse Gas Reporting Program, Toxics Release Inventory, and Clean Air Markets Division Acid Rain Program and Clean Air Interstate Rule.
- Public drinking water systems permitted under the Safe Drinking Water Act, including data from the Safe Drinking Water Information System.
- Hazardous Waste Handlers permitted under the Resource Conservation and Recovery Act, with data drawn from the RCRAInfo data system.
- Facilities permitted under the Clean Water Act and the National Pollutant Discharge Elimination Systems (NPDES) program, including data from EPA’s ICIS-NPDES system and possibly water body information from EPA’s ATTAINS data system.

`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.

- `echoAirGetMeta()` - Returns variable name and descriptions for parameters returned in air facility queries.

- `echoSDWGetMeta()` - Returns variable name and descriptions for parameters returned in public water system queries.

- `echoWaterGetMeta()` - Returns variable name and descriptions for parameters returned in water discharge facility queries (e.g. facilities with an NPDES permit).

- `echoWaterGetParams()` - Search parameter codes for constituent pollutants regulated under NPDES permits.

### Query Facilities

Search and return facility information based on lookup parameters.

- `echoAirGetFacilityInfo()` - Returns a dataframe of permitted air discharge facilities and associated information based on lookup parameters specified by the user.

- `echoSDWGetSystems()` - Returns a dataframe of permitted air discharge facilities and associated information based on lookup parameters specified by the user.

- `echoWaterGetFacilityInfo()` - Returns a dataframe of permitted water discharge facilities and associated information based on lookup parameters specified by the user.

### Reports

Search and return discharge and emissions reports for specified facilities.

- `echoGetCAAPR()` - Returns a dataframe with reported annual air emissions from permitted facilities.

- `echoGetEffluent()` - Returns a dataframe with reported water effluent discharges from permitted 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:

    library(echor)
    meta <- echoAirGetMeta()
    meta
    #> # A tibble: 133 x 6
    #>    ColumnName    DataType DataLength ColumnID ObjectName   Description
    #>    <chr>         <chr>    <chr>      <chr>    <chr>        <chr>
    #>  1 AIR_NAME      VARCHAR2 200        1        AIRName      The name of the AIR ~
    #>  2 SOURCE_ID     VARCHAR2 30         2        SourceID     Unique Identifier as~
    #>  3 AIR_STREET    VARCHAR2 200        3        AIRStreet    The street address o~
    #>  4 AIR_CITY      VARCHAR2 100        4        AIRCity      The city where the A~
    #>  5 AIR_STATE     CHAR     2          5        AIRState     The state where the ~
    #>  6 LOCAL_CONTRO~ CHAR     3          6        LocalContro~ Code for regions wit~
    #>  7 AIR_ZIP       VARCHAR2 10         7        AIRZip       The five-digit zip c~
    #>  8 REGISTRY_ID   VARCHAR2 50         8        RegistryID   An internal 12-digit~
    #>  9 AIR_COUNTY    VARCHAR2 100        9        AIRCounty    The name of the coun~
    #> 10 AIR_EPA_REGI~ CHAR     2          10       AIREPARegion The EPA region where~
    #> # ... with 123 more rows

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 recommend 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 specify the returned information with the `qcolumns` argument. Each argument should be passed 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”.

    library(echor)

    ## Retrieve information about facilities within a geographic location
    df <- echoAirGetFacilityInfo(output = "df",
                                 xmin = '-96.387509',
                                 ymin = '30.583572',
                                 xmax = '-96.281422',
                                 ymax = '30.640008',
                                 qcolumns = "1,2,3,22,23")

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
BRYAN CERAMICS PLANT | TX0000004804100027 | 1500 INDEPENDENCE AVE | 30.63760 | -96.36235
BRYAN CLEANERS & LAUNDRY | 06000000480416E012 | 1803 HOLLEMAN DRIVE | 30.61225 | -96.31750
CITY OF BRYAN | TX0000004804100026 | 1.5 MI W OF @FM 1687 & FM 2818 | 30.63760 | -96.36235

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:

    df <- echoGetCAAPR(p_id = '110000350174')

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 | Nitrous oxide | MTCO2e | GHG | 2009 | NA
CP&L - SUTTON PLANT | 110000350174 | 801 SUTTON STEAM PLANT ROAD | WILMINGTON | NC | 28401 | NEW HANOVER | 04 | 34.28332 | -77.98523 | Chromium(VI) | Pounds | NEI | 2009 | NA
CP&L - SUTTON PLANT | 110000350174 | 801 SUTTON STEAM PLANT ROAD | WILMINGTON | NC | 28401 | NEW HANOVER | 04 | 34.28332 | -77.98523 | Cumene | Pounds | NEI | 2009 | NA
CP&L - SUTTON PLANT | 110000350174 | 801 SUTTON STEAM PLANT ROAD | WILMINGTON | NC | 28401 | NEW HANOVER | 04 | 34.28332 | -77.98523 | Methyl tert-butyl ether | Pounds | NEI | 2009 | NA
CP&L - SUTTON PLANT | 110000350174 | 801 SUTTON STEAM PLANT ROAD | WILMINGTON | NC | 28401 | NEW HANOVER | 04 | 34.28332 | -77.98523 | Mercury compounds | Pounds | TRI | 2009 | 110
CP&L - SUTTON PLANT | 110000350174 | 801 SUTTON STEAM PLANT ROAD | WILMINGTON | NC | 28401 | NEW HANOVER | 04 | 34.28332 | -77.98523 | Nitrogen oxides | Pounds | CAMD | 2009 | 8544200

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 facilities with NPDES permits to discharge wastewater:

    df <- echoWaterGetFacilityInfo(xmin = '-96.407563', ymin = '30.554395',
                                   xmax = '-96.25947',  ymax = '30.751984',
                                   output = 'df')

CWPName | SourceID | CWPStreet | CWPCity | CWPState | CWPStateDistrict | CWPZip | MasterExternalPermitNmbr | RegistryID | CWPCounty | CWPEPARegion | FacDerivedHuc | FacLat | FacLong | CWPTotalDesignFlowNmbr | CWPActualAverageFlowNmbr | DschToMs4 | ExposedActivity | Subsector | CWPVersionNmbr | SubmittedDate | CWPPermitTypeDesc | CWPIssueDate | CWPTerminationDate | CWPSNCStatus | CWPCsoOutfalls
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
777 GRAHAM RD | TXR1578AE | 777 GRAHAM RD | COLLEGE STATION | TX |  | 77845 | TXR150000 | 110070621969 |  | 06 | 12070103 | 30.57004 | -96.29493 | NA | NA |  |  |  | 0 | NA | General Permit Covered Facility | 2019-09-23 | NA |  | NA
ACE TOWNHOME | TXR15667I | 2136 CHESTNUT OAK CIR | COLLEGE STATION | TX |  | 77845-4168 | TXR150000 | 110070364352 |  | 06 | 12070103 | 30.61411 | -96.28490 | NA | NA |  |  |  | 0 | NA | General Permit Covered Facility | 2018-06-01 | NA |  | NA
AGGIE ACRES WWTP | TX0132187 | 800 FT SE OF N DOWLING RD APPROX 600 FT SW OF WALN | COLLEGE STATION | TX | 09 | 77845 |  | 110064633829 | Brazos | 06 |  | 30.55565 | -96.29110 | NA | NA |  |  |  | 0 | NA | NPDES Individual Permit | NA | NA |  | NA
AGRIVEST SWINE FEEDLOT | TX0121240 | SWISHER COUNTY | BRYAN | TX | 01 | 00000 |  | 110039193271 | Swisher | 06 |  | 30.66658 | -96.36552 | NA | NA |  |  |  | 0 | NA | NPDES Individual Permit | 2000-01-14 | 2000-10-30 |  | NA
ALENCO WINDOWS | TXR05U808 | 615 W CARSON ST | BRYAN | TX |  | 77801-1102 | TXR050000 | 110000464284 | Brazos | 06 | 12070103 | 30.64457 | -96.37270 | NA | NA | N |  |  | 0 | 2016-10-05 | General Permit Covered Facility | 2016-10-28 | NA |  | NA
ANDREWS ORTHODONTIST AND RETAIL BUILDING | TXR15193R | 1098 ARRINGTON RD | COLLEGE STATION | TX |  | 77845 | TXR150000 | 110070368658 |  | 06 | 12070103 | 30.55800 | -96.26566 | NA | NA |  |  |  | 0 | NA | General Permit Covered Facility | 2018-08-27 | 2019-07-18 |  | NA

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:

    df <- echoGetEffluent(p_id = 'tx0119407', parameter_code = '50050')
    #> Warning: 154 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.

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
3600178396 | TX0119407 | 4 | 3600049681 | 001 | EXO | External Outfall | 3600061722 | 3600073706 | 3600437316 | ENF | 08/01/2015 | 03/01/2020 | 1 | 50050 | Flow, in conduit or thru treatment plant | 1 | Effluent Gross |  |  | 3600678123 | Q1 | Quantity1 | .131 | 03 | MGD | 03 | MGD | .131 | DB | DAILY AV | AVG | Average | <= |  | 3600838773 | 10/31/2016 | 3610877102 | Q1 | Quantity1 | 3630384878 | .0623 | 03 | MGD | .0623 | = | 11/18/2016 |  |  |  |  |  |  |  |  |  |  |  |  |  | No Violation Identified
| 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
3600178396 | TX0119407 | 4 | 3600049681 | 001 | EXO | External Outfall | 3600061722 | 3600073706 | 3600437316 | ENF | 08/01/2015 | 03/01/2020 | 1 | 50050 | Flow, in conduit or thru treatment plant | 1 | Effluent Gross |  |  | 3600678122 | Q2 | Quantity2 |  | 03 | MGD | 03 | MGD |  | DD | DAILY MX | MAX | Maximum |  |  | 3600838773 | 10/31/2016 | 3610877106 | Q2 | Quantity2 | 3630384880 | .075 | 03 | MGD | .075 | = | 11/18/2016 |  |  |  |  |  |  |  |  |  |  |  |  |  | No Violation Identified

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`.

    echoWaterGetParams(term = "Oxygen, dissolved")
    #> # A tibble: 5 x 2
    #>   ValueCode ValueDescription
    #>   <chr>     <chr>
    #> 1 00300     Oxygen, dissolved [DO]
    #> 2 51646     Oxygen, dissolved [DO] maximum
    #> 3 51645     Oxygen, dissolved [DO] minimum
    #> 4 00301     Oxygen, dissolved percent saturation
    #> 5 00399     Oxygen, dissolved, % of time violated

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: 1728 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: 6 parsing failures.
    #> row col           expected actual         file
    #>   1   { delimiter or quote      : <raw vector>
    #>   1   { delimiter or quote      E <raw vector>
    #>   1   { delimiter or quote      : <raw vector>
    #>   1   { delimiter or quote      E <raw vector>
    #>   1   { delimiter or quote      : <raw vector>
    #> ... ... .................. ...... ............
    #> See problems(...) for more details.
    df <- df %>%
      tidyr::unnest(dmr)
    tibble::glimpse(df)
    #> Observations: 2,595
    #> Variables: 63
    #> $ permit                      <chr> "TX0119407", "TX0119407", "TX0119407", ...
    #> $ activity_id                 <chr> "", "", "3600178396", "", "", "36001783...
    #> $ npdes_id                    <chr> NA, NA, "TX0119407", NA, NA, "TX0119407...
    #> $ version_nmbr                <chr> NA, NA, "4", NA, NA, "4", NA, NA, "4", ...
    #> $ perm_feature_id             <chr> NA, NA, "3600049681", NA, NA, "36000496...
    #> $ perm_feature_nmbr           <chr> NA, NA, "001", NA, NA, "001", NA, NA, "...
    #> $ perm_feature_type_code      <chr> NA, NA, "EXO", NA, NA, "EXO", NA, NA, "...
    #> $ perm_feature_type_desc      <chr> NA, NA, "External Outfall", NA, NA, "Ex...
    #> $ limit_set_id                <chr> NA, NA, "3600061722", NA, NA, "36000617...
    #> $ limit_set_schedule_id       <chr> NA, NA, "3600073706", NA, NA, "36000737...
    #> $ limit_id                    <chr> NA, NA, "3600437315", NA, NA, "36004373...
    #> $ limit_type_code             <chr> NA, NA, "ENF", NA, NA, "ENF", NA, NA, "...
    #> $ limit_begin_date            <chr> NA, NA, "08/01/2015", NA, NA, "08/01/20...
    #> $ limit_end_date              <chr> NA, NA, "03/01/2020", NA, NA, "03/01/20...
    #> $ nmbr_of_submission          <chr> NA, NA, "1", NA, NA, "1", NA, NA, "1", ...
    #> $ parameter_code              <chr> NA, NA, "00300", NA, NA, "00300", NA, N...
    #> $ parameter_desc              <chr> NA, NA, "Oxygen, dissolved [DO]", NA, N...
    #> $ monitoring_location_code    <chr> NA, NA, "1", NA, NA, "1", NA, NA, "1", ...
    #> $ monitoring_location_desc    <chr> NA, NA, "Effluent Gross", NA, NA, "Effl...
    #> $ stay_type_code              <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ stay_type_desc              <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ limit_value_id              <chr> NA, NA, "3600678121", NA, NA, "36006781...
    #> $ limit_value_type_code       <chr> NA, NA, "C1", NA, NA, "C1", NA, NA, "C1...
    #> $ limit_value_type_desc       <chr> NA, NA, "Concentration1", NA, NA, "Conc...
    #> $ limit_value_nmbr            <chr> NA, NA, "4", NA, NA, "4", NA, NA, "4", ...
    #> $ limit_unit_code             <chr> NA, NA, "19", NA, NA, "19", NA, NA, "19...
    #> $ limit_unit_desc             <chr> NA, NA, "mg/L", NA, NA, "mg/L", NA, NA,...
    #> $ standard_unit_code          <chr> NA, NA, "19", NA, NA, "19", NA, NA, "19...
    #> $ standard_unit_desc          <chr> NA, NA, "mg/L", NA, NA, "mg/L", NA, NA,...
    #> $ limit_value_standard_units  <chr> NA, NA, "4", NA, NA, "4", NA, NA, "4", ...
    #> $ statistical_base_code       <chr> NA, NA, "MO", NA, NA, "MO", NA, NA, "MO...
    #> $ statistical_base_short_desc <chr> NA, NA, "MO MIN", NA, NA, "MO MIN", NA,...
    #> $ statistical_base_type_code  <chr> NA, NA, "MIN", NA, NA, "MIN", NA, NA, "...
    #> $ statistical_base_type_desc  <chr> NA, NA, "Minimum", NA, NA, "Minimum", N...
    #> $ limit_value_qualifier_code  <chr> NA, NA, ">=", NA, NA, ">=", NA, NA, ">=...
    #> $ stay_value_nmbr             <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ dmr_event_id                <chr> NA, NA, "3600838773", NA, NA, "36008388...
    #> $ monitoring_period_end_date  <chr> NA, NA, "10/31/2016", NA, NA, "11/30/20...
    #> $ dmr_form_value_id           <chr> NA, NA, "3610877053", NA, NA, "36108772...
    #> $ value_type_code             <chr> NA, NA, "C1", NA, NA, "C1", NA, NA, "C1...
    #> $ value_type_desc             <chr> NA, NA, "Concentration1", NA, NA, "Conc...
    #> $ dmr_value_id                <chr> NA, NA, "3630384863", NA, NA, "36315835...
    #> $ dmr_value_nmbr              <chr> NA, NA, "5.91", NA, NA, "6.2", NA, NA, ...
    #> $ dmr_unit_code               <chr> NA, NA, "19", NA, NA, "19", NA, NA, "19...
    #> $ dmr_unit_desc               <chr> NA, NA, "mg/L", NA, NA, "mg/L", NA, NA,...
    #> $ dmr_value_standard_units    <chr> NA, NA, "5.91", NA, NA, "6.2", NA, NA, ...
    #> $ dmr_value_qualifier_code    <chr> NA, NA, "=", NA, NA, "=", NA, NA, "=", ...
    #> $ value_received_date         <chr> NA, NA, "11/18/2016", NA, NA, "12/20/20...
    #> $ days_late                   <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ nodi_code                   <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ nodi_desc                   <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ exceedence_pct              <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ npdes_violation_id          <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ violation_code              <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ violation_desc              <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ rnc_detection_code          <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ rnc_detection_desc          <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ rnc_detection_date          <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ rnc_resolution_code         <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ rnc_resolution_desc         <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ rnc_resolution_date         <chr> NA, NA, "", NA, NA, "", NA, NA, "", NA,...
    #> $ violation_severity          <chr> NA, NA, "No Violation Identified", NA, ...
    #> $ `{`                         <chr> NA, NA, NA, NA, NA, NA, NA, NA, 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.

    ## Sample code only,
    ## This example requires the development
    ## version of ggplot2 with support for
    ## geom_sf()

    library(ggplot2)
    library(ggmap)
    library(dplyr)
    library(purrr)
    library(sf)
    library(ggrepel)

    ## Download data as a simple feature
    df <- echoWaterGetFacilityInfo(xmin = '-96.407563', ymin = '30.554395',
                                            xmax = '-96.25947', ymax = '30.751984',
                                            output = 'sf')
    ## Download a basemap with gg_map
    collegestation <- get_map(location = c(-96.387509, 30.583572,
                                           -96.281422, 30.640008),
                              zoom = 14, maptype = "toner")

    ## Use coordinates to create label locations
    df <- df %>%
      mutate(
        coords = map(geometry, st_coordinates),
        coords_x = map_dbl(coords, 1),
        coords_y = map_dbl(coords, 2)
      )

    ## Make the map
    ggmap(collegestation) +
      geom_sf(data = df, inherit.aes = FALSE, shape = 21,
              color = "darkred", fill = "darkred",
              size = 2, alpha = 0.25) +
      geom_label_repel(data = df, aes(x = coords_x, y = coords_y, label = SourceID),
                       point.padding = .5, min.segment.length = 0.1,
                       size = 2, color = "dodgerblue") +
      labs(x = "Longitude", y = "Latitude",
           title = "NPDES permits near Texas A&M",
           caption = "Source: EPA ECHO database")