PUDL (Public Utility Data Linkage)
repository·main·Indexed 20 days ago
https://github.com/catalyst-cooperative/pudlAn open data processing pipeline for US energy data. PUDL provides tools and notebooks for processing, analyzing, and modeling public utility data, including workflows for validating Excel column mappings, debugging EIA ETL processes via Dagster assets, and managing FERC-EIA manual mapping spreadsheets.
What's inside PUDL
- PUDL (Public Utility Data Liberation Project) is a data processing pipeline that cleans, integrates, and standardizes widely used US public energy datasets. It is designed to make complex, semi-structured government data accessible for researchers, activists, and policymakers by providing standardized, machine-readable versions (primarily Parquet files and SQLite databases).
Overview of PUDL data validation
mainPUDL uses
dbtfor data validation. In this setup, every validation test is a SQL query designed to select rows that fail the test; a successful test returns no results.Validation relies on:
- dbt built-in data tests.
- The
dbt_expectationspackage. - Custom data tests defined within PUDL.
Validation Standards:
- Full ETL vs. Fast ETL: All tests should pass on both outputs, except for row count checks, which only apply to Full ETL outputs.
- Row Counts: All tables should have row count checks unless they have a non-deterministic number of rows. Non-deterministic tables should use
expect_table_row_count_to_be_between. - Null Columns: Full ETL outputs should not have entirely null columns. For Fast ETL outputs containing deprecated columns, per-year nullness expectations should be added using the
pudl.scripts.pudl_null_colsscript.
Asset Naming Conventions in PUDL
mainPUDL uses Dagster assets organized into three processing layers: Raw, Core, and Output. Asset names are used as table or file names and follow a specific hierarchical pattern to indicate their processing stage and origin.
General Pattern
{layer}_{source}__{asset_type}_{asset_name}- layer: The processing stage (
raw,core, orout). - source: An abbreviation of the data source (e.g.,
eia860,ferc1). - asset_type: Describes how the asset is modeled (e.g.,
assn,entity,scd). - asset_name: Describes the entity, categorical code type, or measurement.
Layer-Specific Conventions
Raw Layer
Contains direct extracts from source data, typically persisted as pickle files.
- Pattern:
raw_{source}__{asset_name} - Note:
asset_typeis omitted here as data is not yet modeled to PUDL standards.
Core Layer
Contains well-modeled, denormalized tables (Tidy Data) that serve as building blocks. Stored as parquet or database tables.
- Pattern:
core_{source}__{asset_type}_{asset_name} - Note:
sourcemay bepudlif the asset is a derived connection created by PUDL contributors.
Output Layer
Contains wide, complete tables designed for end-user analysis.
- Pattern:
out_{source}__{asset_type}_{asset_name} - Note:
sourceandasset_typeare optional in this layer.
Intermediate Assets
Logical steps within a process that are not intended for user access or persistence. These are denoted by a preceding underscore (e.g.,
_core_eia860__plants).{layer}_{source}__{asset_type}_{asset_name}- layer: The processing stage (
LLM usage policy for PUDL contributions
mainPUDL allows the use of Large Language Models (LLMs) under the following conditions:
- Human Review is Mandatory: All PRs (internal and external) are reviewed by humans. Code must be optimized for human readability and synthesis.
- Disclose LLM Usage: If you use an LLM to generate content (e.g., tests or implementation plans), you must briefly describe how it was used in the PR description (e.g., "I used an LLM to generate these tests, and cleaned them up by hand").
- No Vendor Lock-in: Any additions to Catalyst LLM tooling will be rejected if they require a specific proprietary model or harness. The project prioritizes open tooling and openly licensed models.
Understand PUDL Dagster abstractions
mainPUDL uses Dagster for data orchestration. The following core abstractions are used:
- Definitions: The top-level collection of Dagster objects (assets, jobs, resources, etc.). In PUDL,
pudl.dagsteris the canonical assembly, whilepudl.definitionsis the stable entry point for thedgCLI. - Assets: The primary building blocks representing data entities (e.g., database tables or Parquet files). Most assets in PUDL are
pandas.DataFrameobjects. - Resources: Objects providing access to external systems. Key PUDL resources include
pudl.workspace.datastore.Datastore(for Zenodo data),pudl.workspace.datastore.ZenodoDoiSettings, andpudl.dagster.resources.GlobalDataConfigResource. - IO Managers: Handle the separation of processing logic from data persistence. PUDL uses managers for FERC SQLite databases, Parquet files, and SQLite files.
pudl.dagster.io_managers.PudlMixedFormatIOManagerprovides a single interface for both SQLite and Parquet. - Jobs: Preconfigured collections of assets, resources, and IO Managers. Major jobs include:
ferc_to_sqlite: Rebuilds raw FERC prerequisite databases.pudl: Runs the main ETL (requires raw FERC databases).pudl_with_ferc_to_sqlite: Full end-to-end build.ferceqr: DuckDB-based pipeline for large FERC EQR datasets.
- Configs: Runtime settings passed to jobs/assets, typically stored in YAML files like
dg_fast.ymlordg_full.yml.
- Definitions: The top-level collection of Dagster objects (assets, jobs, resources, etc.). In PUDL,
Provide Complete and Continuous Time Series
mainMost PUDL data consists of time series (hourly to annual). To ensure compatibility with time series analysis tools, follow these requirements:
- Contiguous Time Series: Provide continuous ranges of time. Avoid gaps (e.g., providing 2009-2010 and 2016-2018 while skipping 2011-2015).
- Complete Time Series: Ensure all timesteps are present in the series. If a value is missing for a specific timestep, provide it as
NArather than omitting the row entirely.
Use subsidiary_company_id_sec10k for tracking
mainThe identifier
subsidiary_company_id_sec10kis used to track subsidiaries over time. It is constructed from three components:- The filer company’s Central Index Key (CIK)
- The subsidiary company name
- The subsidiary’s location of incorporation
Usage Constraints:
- Consistent Tracking: The same subsidiary reported by the same filer across multiple years will have a consistent
subsidiary_company_id_sec10k. - No Cross-Filer Linking: If the same subsidiary appears in filings from different parent companies, it will receive a different identifier in each context. Do not use this ID to link the same subsidiary across different filers.
Understand the SEC 10-K Ownership Data Extraction Model
mainThe SEC 10-K ownership data extraction process uses machine learning to transform unstructured Exhibit 21 attachments from SEC Form 10-K filings into structured tables.
Key Workflow:
- Extraction: A fine-tuned
LayoutLMv3model performs named entity recognition (NER) on Exhibit 21 documents to classify tokens assubsidiary name,location of incorporation,ownership percentage, orother. - Structuring: A rules-based heuristic model uses bounding box coordinates and entity tags to organize these tokens into structured tables.
- Linkage: Probabilistic record linkage (using
Splink) connects these extracted companies to EIA (Energy Information Administration) utilities, enabling connections to PUDL data.
Note: This dataset is currently in beta. The contents and connections are probabilistic in nature.
- Extraction: A fine-tuned
Understand PUDL's dbt architecture and quirks
mainPUDL's use of dbt is specialized because Dagster coordinates the pipeline, and dbt is used strictly for validation rather than transformation.
Key Architectural Details:
- Tables as Sources: Most PUDL tables are treated as dbt
sources(external tables) rather thanmodels. dbt assumes these tables exist and does not attempt to create them. - DuckDB & Parquet: Tables are stored as Apache Parquet files and queried via DuckDB. Because of this, some dbt functionality—specifically the
dbt adapterobject—is unavailable in test definitions because it cannot access the underlying database schema. - Intermediate Tables: Some intermediate tables are defined as true dbt
modelsto simplify tests. These are materialized as views in a DuckDB database located at$PUDL_OUTPUT/pudl_dbt_tests.duckdb. When debugging these specific tables, you must connect to this DuckDB database.
- Tables as Sources: Most PUDL tables are treated as dbt
How PUDL releases data
mainPUDL is designed as an end-use application that produces data for consumption by other applications, rather than a library for Python dependencies. Consequently, PUDL does not release installable packages on PyPI or
conda-forge.Release Process:
- Versioned releases are tagged on
mainusing a calendar-based format (e.g.,v2023.07.15). - Tagged releases trigger an archive of the repository on Zenodo.
- Nightly build outputs for tagged releases are archived on Zenodo and made available via the AWS Open Data Registry.
- Versioned releases are tagged on
Identify PUDL Entity Table Types
mainFor each entity type, PUDL typically produces two distinct types of tables to handle different data lifecycles:
- Static Entity Tables: Contain attributes expected to be stable over time (e.g.,
core_eia__entity_plants). These tables always includeentityin their name and have one row per unique entity. - Yearly Slowly Changing Dimension (SCD) Tables: Contain attributes expected to vary slightly over time (e.g.,
core_eia860__scd_plants). These tables always includescdin their name and have one row per entity per report year.
Supported EIA Entities and IDs:
- Utilities:
utility_id_eia - Plants:
plant_id_eia - Boilers:
plant_id_eia,boiler_id - Generators:
plant_id_eia,generator_id
For forensic auditing, PUDL also provides tables with
forensics_entity_resolutionin their names, which contain all raw values used during the resolution process.- Static Entity Tables: Contain attributes expected to be stable over time (e.g.,
Access raw government data inputs
mainPUDL archives minimally processed versions of the raw data published by governments. This is useful if you need to see original data that is difficult to find, or if you want to see how data looked before it was revised or deleted by the source.
These datasets are unmodified except for minimal processing (such as compression or grouping into ZIP archives) and the addition of metadata to assist identification. You can find these archives in the Catalyst Cooperative Community on Zenodo.