Source code for pudl.extract.epacems
"""
Retrieve data from EPA CEMS hourly zipped CSVs.
This modules pulls data from EPA's published CSV files.
"""
import logging
import pandas as pd
import pudl.constants as pc
import pudl.workspace.datastore as datastore
logger = logging.getLogger(__name__)
[docs]def read_cems_csv(filename):
"""
Read a CEMS CSV file, compressed or not, into a :class:`pandas.DataFrame`.
Note that some columns are not read. See
:mod:`pudl.constants.epacems_columns_to_ignore`. Data types for the columns
are specified in :mod:`pudl.constants.epacems_csv_dtypes` and names of the
output columns are set by :mod:`pudl.constants.epacems_rename_dict`.
Args:
filename (str): The name of the file to be read
Returns:
pandas.DataFrame: A DataFrame containing the contents of the
CSV file.
"""
df = pd.read_csv(
filename,
index_col=False,
usecols=lambda col: col not in pc.epacems_columns_to_ignore,
dtype=pc.epacems_csv_dtypes,
).rename(columns=pc.epacems_rename_dict)
return df
[docs]def extract(epacems_years, states, data_dir):
"""
Coordinate the extraction of EPA CEMS hourly DataFrames.
Args:
epacems_years (list): The years of CEMS data to extract, as 4-digit
integers.
states (list): The states whose CEMS data we want to extract, indicated
by 2-letter US state codes.
data_dir (path-like): Path to the top directory of the PUDL datastore.
Yields:
dict: a dictionary with a single EPA CEMS tabular data resource name as
the key, having the form "hourly_emissions_epacems_YEAR_STATE" where
YEAR is a 4 digit number and STATE is a lower case 2-letter code for a
US state. The value is a :class:`pandas.DataFrame` containing all the
raw EPA CEMS hourly emissions data for the indicated state and year.
"""
for year in epacems_years:
# The keys of the us_states dictionary are the state abbrevs
for state in states:
dfs = []
logger.info(f"Performing ETL for EPA CEMS hourly {state}-{year}")
for month in range(1, 13):
filename = datastore.path('epacems',
year=year, month=month, state=state,
data_dir=data_dir)
dfs.append(read_cems_csv(filename))
# Return a dictionary where the key identifies this dataset
# (just like the other extract functions), but unlike the
# others, this is yielded as a generator (and it's a one-item
# dictionary).
yield {
("hourly_emissions_epacems_" + str(year) + "_" + state.lower()):
pd.concat(dfs, sort=True, copy=False, ignore_index=True)
}