pudl.output.ferc714#
Functions & classes for compiling derived aspects of the FERC Form 714 data.
For a narrative overview of the timeseries imputation process, see the documentation at Timeseries Imputation
Attributes#
Explicit year-to-year repair instructions for EIA-861 balancing authority data. |
|
Balancing authorities to treat as utilities in associations from EIA 861. |
|
Classes#
Functions#
|
Categorize FERC 714 |
|
Filter source rows by exclude_states, raising if all rows are eliminated. |
Modified core_eia861__yearly_balancing_authority table. |
|
Modified core_eia861__assn_balancing_authority table. |
|
Modified core_eia861__yearly_service_territory table. |
|
|
Broadcast respondent data across all years with reported demand. |
|
Annualized respondents with |
|
Annual respondents with the county FIPS IDs for their service territories. |
Annual respondents with all associated county-level geometries. |
|
Annual respondents with a single all-encompassing geometry for each year. |
|
|
Compile annualized, categorized respondents and summarize values. |
Module Contents#
- class pudl.output.ferc714.BaFix(/, **data: Any)[source]#
Bases:
pydantic.BaseModelA single BA data repair entry for one target year.
id: EIA balancing authority identifier (balancing_authority_id_eia).source_year: The year whose data is used as a template for the repair.exclude_states: Optional list of two-letter state codes. Utility associations for utilities in these states are omitted when copying fromsource_year.
- class pudl.output.ferc714.BaFixMap[source]#
Bases:
pydantic.RootModel[dict[int,list[BaFix]]]Validated mapping of target years to lists of
BaFixrepair entries.Raises
pydantic.ValidationErrorfor malformed entries (wrong types, unknown keys) andValueErrorfor cross-entry constraint violations: duplicate BA IDs within the same target year, and self-referential fixes wheresource_year == target_year. Instantiated once at module load as theBA_FIXESconstant.
- pudl.output.ferc714.BA_FIXES[source]#
Explicit year-to-year repair instructions for EIA-861 balancing authority data.
Each key is a target year that requires a manual repair for one or more balancing authorities. Each value is a list of
BaFixentries describing which BA to repair and which singlesource_yearshould be treated as the authoritative template for that specific target year.The fixes are consumed by three functions:
filled_core_eia861__yearly_balancing_authority(),filled_core_eia861__assn_balancing_authority(), andfilled_core_eia861__yearly_service_territory(). They all use the same explicitsource_year -> target_yearmappings, but apply them differently:filled_core_eia861__yearly_balancing_authorityfills missing BA id rows for a target year without overwriting any existing target rows.filled_core_eia861__assn_balancing_authorityreplaces the target-yearBA-utility association rows with rows copied from
source_year.
filled_core_eia861__yearly_service_territorylimits itself to the utility-state-yearcombinations implicated by those explicit fixes and copies county coverage from the nearest available relevant year when needed.
This is not a forward-fill or backward-fill across all years. Data from one year is only applied to another year when a
source_year -> target_yearpair is listed here.All three functions silently skip a target year that is not present in the available EIA-861 data, and log a warning when the target year is present but the
source_yearrequired for the repair is not.To add a new fix: identify the target year(s), the affected BA’s
balancing_authority_id_eia, and asource_yearwhose data is correct. If certain states should be excluded from the copy, addexclude_states.
- pudl.output.ferc714.UTILITIES: list[dict[str, Any]][source]#
Balancing authorities to treat as utilities in associations from EIA 861.
The changes are applied locally to EIA 861 tables.
id(int): EIA balancing authority (BA) identifier (balancing_authority_id_eia). Rows foridare removed fromcore_eia861__yearly_balancing_authority.reassign(Optional[bool]): Whether to reassign utilities to parent BAs. Rows foridas BA incore_eia861__assn_balancing_authorityare removed. Utilities assigned toidfor a given year are reassigned to the BAs for whichidis an associated utility.replace(Optional[bool]): Whether to remove rows whereidis a utility incore_eia861__assn_balancing_authority. Applies only ifreassign=True.
- pudl.output.ferc714.categorize_eia_code(eia_codes: list[int], ba_ids: list[int], util_ids: list[int], priority: str = 'balancing_authority') pandas.DataFrame[source]#
Categorize FERC 714
eia_codesas either balancing authority or utility IDs.Most FERC 714 respondent IDs are associated with an
eia_codewhich refers to either abalancing_authority_id_eiaor autility_id_eiabut no indication as to which type of ID each one is. This is further complicated by the fact that EIA uses the same numerical ID to refer to the same entity in most but not all cases, when that entity acts as both a utility and as a balancing authority.This function associates a
respondent_typeofutility,balancing_authorityorpandas.NAwith each inputeia_codeusing the following rules:If a
eia_codeappears only inutil_idstherespondent_typewill beutility.If
eia_codeappears only inba_idstherespondent_typewill be assignedbalancing_authority.If
eia_codeappears in neither set of IDs,respondent_typewill be assignedpandas.NA.If
eia_codeappears in both sets of IDs, then whicheverrespondent_typehas been selected with thepriorityflag will be assigned.
Note that the vast majority of
balancing_authority_id_eiavalues also show up asutility_id_eiavalues, but only a small subset of theutility_id_eiavalues are associated with balancing authorities. If you usepriority="utility"you should probably also be specifically compiling the list of Utility IDs because you know they should take precedence. If you use utility priority with all utility IDs- Parameters:
eia_codes – A collection of IDs which may be either associated with EIA balancing authorities or utilities, to be categorized.
ba_ids_eia – A collection of IDs which should be interpreted as belonging to EIA Balancing Authorities.
util_ids_eia – A collection of IDs which should be interpreted as belonging to EIA Utilities.
priority – Which respondent_type to give priority to if the eia_code shows up in both util_ids_eia and ba_ids_eia. Must be one of “utility” or “balancing_authority”. The default is “balancing_authority”.
- Returns:
eia_codeandrespondent_type.- Return type:
A DataFrame containing 2 columns
- pudl.output.ferc714._apply_exclude_states(ref: pandas.DataFrame, fix: BaFix, target_year: int) pandas.DataFrame[source]#
Filter source rows by exclude_states, raising if all rows are eliminated.
An empty result after filtering means the exclude_states list is broader than the actual data, which would silently drop all associations for the (BA, target_year) pair. That is almost certainly an erroneous specification.
- pudl.output.ferc714.filled_core_eia861__yearly_balancing_authority(core_eia861__yearly_balancing_authority: pandas.DataFrame) pandas.DataFrame[source]#
Modified core_eia861__yearly_balancing_authority table.
Applies the explicit year-to-year repairs described in
BA_FIXESto the BA identity table.Each entry in
BA_FIXESnames onesource_yearand onetarget_yearfor a given balancing authority. If that BA already has a row for the target year, nothing changes. Otherwise, its source-year row is copied and relabeled with the target year’s date. No other years are affected, and no values are interpolated or extrapolated.Silently skips any target year absent from the data. Logs a warning and skips if the target year is present but the source year, or the specific BA row within that source year, is not. Also removes balancing authorities that are manually categorised as utilities via
UTILITIES.
- pudl.output.ferc714.filled_core_eia861__assn_balancing_authority(core_eia861__assn_balancing_authority: pandas.DataFrame) pandas.DataFrame[source]#
Modified core_eia861__assn_balancing_authority table.
Applies the explicit year-to-year repairs described in
BA_FIXESto the BA-utility association table.For each
source_year -> target_yearmapping, replaces all existing rows for the(BA, target_year)pair with rows copied from the source year, optionally filtered byBaFix.exclude_states. This is an explicit year-to-year rewrite of known-bad associations, not a general forward-fill or backward-fill across a range of years.Silently skips target years absent from the data; logs a warning when the target year is present but the source year is not, or when that BA has no source-year rows to copy. In those cases the target-year rows are left unchanged because the repair cannot be applied correctly. Also removes balancing authorities listed in
UTILITIESand, whenreassign=True, re-parents their child utilities to the grandparent BAs.
- pudl.output.ferc714.filled_core_eia861__yearly_service_territory(filled_assn: pandas.DataFrame, core_eia861__yearly_service_territory: pandas.DataFrame) pandas.DataFrame[source]#
Modified core_eia861__yearly_service_territory table.
Applies county-level service territory repairs implied by
BA_FIXES.Selects utility-state-year combinations that are relevant to the explicit
source_year -> target_yearBA repairs inBA_FIXES, covering both the listed target years and the source years used to repair them. It then merges those rows with the service territory to obtain county FIPS data, drops utility-state pairs that have no county data in any explicitly implicated year, and copies county rows onto missing years from the closest other explicitly implicated year for that same utility-state pair.This is not a traditional forward-fill or backward-fill across all years in the dataset. County rows are only copied between years when those years are explicitly implicated by the
source_year -> target_yearmappings inBA_FIXES, and the copy is only used to support those explicit repairs.- Parameters:
filled_assn – The already-repaired BA-utility association table, as returned by
filled_core_eia861__assn_balancing_authority().core_eia861__yearly_service_territory – The raw service territory table.
- pudl.output.ferc714._out_ferc714__annualized_respondents(context, core_ferc714__respondent_id: pandas.DataFrame) pandas.DataFrame[source]#
Broadcast respondent data across all years with reported demand.
The FERC 714 Respondent IDs and names are reported in their own table, without any reference to individual years, but much of the information we are associating with them varies annually. This method creates an annualized version of the respondent table, with each respondent having an entry corresponding to every year for which FERC 714 has been processed. This means that many of the respondents will end up having entries for years in which they reported no demand, and that’s fine. They can be filtered later.
- pudl.output.ferc714._out_ferc714__categorized_respondents(context, core_ferc714__respondent_id: pandas.DataFrame, out_eia__yearly_utilities: pandas.DataFrame, core_eia861__yearly_service_territory: pandas.DataFrame, core_eia861__yearly_balancing_authority: pandas.DataFrame, _out_ferc714__annualized_respondents: pandas.DataFrame) pandas.DataFrame[source]#
Annualized respondents with
respondent_typeassigned if possible.Categorize each respondent as either a
utilityor abalancing_authorityusing the parameters stored in the instance of the class. While categorization can also be done without annualizing, this function annualizes as well, since we are adding therespondent_typein order to be able to compile service territories for the respondent, which vary annually.
- pudl.output.ferc714.out_ferc714__respondents_with_fips(context, _out_ferc714__categorized_respondents: pandas.DataFrame, core_eia861__assn_balancing_authority: pandas.DataFrame, core_eia861__yearly_service_territory: pandas.DataFrame, core_eia861__assn_utility: pandas.DataFrame) pandas.DataFrame[source]#
Annual respondents with the county FIPS IDs for their service territories.
Given the
respondent_typeassociated with each respondent (eitherutilityorbalancing_authority) compile a list of counties that are part of their service territory on an annual basis, and merge those into the annualized respondent table. This results in a very long dataframe, since there are thousands of counties and many of them are served by more than one entity.Currently respondents categorized as
utilitywill include any county that appears in thecore_eia861__yearly_service_territorytable in association with that utility ID in each year, while forbalancing_authorityrespondents, some counties can be excluded based on state (iflimit_by_state==True).
- pudl.output.ferc714._out_ferc714__georeferenced_counties(out_ferc714__respondents_with_fips: pandas.DataFrame, out_censusdp1tract__counties: geopandas.GeoDataFrame) geopandas.GeoDataFrame[source]#
Annual respondents with all associated county-level geometries.
Given the county FIPS codes associated with each respondent in each year, pull in associated geometries from the US Census DP1 dataset, so we can do spatial analyses. This keeps each county record independent – so there will be many records for each respondent in each year. This is fast, and still good for mapping, and retains all of the FIPS IDs so you can also still do ID based analyses.
- pudl.output.ferc714.out_ferc714__georeferenced_respondents(out_ferc714__respondents_with_fips: pandas.DataFrame, out_ferc714__summarized_demand: pandas.DataFrame, out_censusdp1tract__counties: geopandas.GeoDataFrame) geopandas.GeoDataFrame[source]#
Annual respondents with a single all-encompassing geometry for each year.
Given the county FIPS codes associated with each responent in each year, compile a geometry for the respondent’s entire service territory annually. This results in just a single record per respondent per year, but is computationally expensive and you lose the information about what all counties are associated with the respondent in that year. But it’s useful for merging in other annual data like total demand, so you can see which respondent-years have both reported demand and decent geometries, calculate their areas to see if something changed from year to year, etc.
- pudl.output.ferc714.out_ferc714__summarized_demand(_out_ferc714__annualized_respondents: pandas.DataFrame, out_ferc714__hourly_planning_area_demand: pandas.DataFrame, _out_ferc714__categorized_respondents: pandas.DataFrame, _out_ferc714__georeferenced_counties: geopandas.GeoDataFrame) pandas.DataFrame[source]#
Compile annualized, categorized respondents and summarize values.
Calculated summary values include: * Total reported electricity demand per respondent (
demand_annual_mwh) * Reported per-capita electrcity demand (demand_annual_per_capita_mwh) * Population density (population_density_km2) * Demand density (demand_density_mwh_km2)These metrics are helpful identifying suspicious changes in the compiled annual geometries for the planning areas.