Git Product home page Git Product logo

catalyst-cooperative / pudl Goto Github PK

View Code? Open in Web Editor NEW
444.0 18.0 101.0 418.81 MB

The Public Utility Data Liberation Project provides analysis-ready energy system data to climate advocates, researchers, policymakers, and journalists.

Home Page: https://catalyst.coop/pudl

License: MIT License

Python 98.72% Shell 0.37% Jinja 0.59% Dockerfile 0.07% HCL 0.07% Mako 0.01% Makefile 0.17%
open-data ferc eia energy utility climate electricity epa coal natural-gas

pudl's Introduction

The Public Utility Data Liberation Project (PUDL)

Project Status: Active

PyTest Status

Codecov Test Coverage

Read the Docs Build Status

Any color you want, so long as it's black.

pre-commit CI

Zenodo DOI

What is PUDL?

The PUDL Project is an open source data processing pipeline that makes US energy data easier to access and use programmatically.

Hundreds of gigabytes of valuable data are published by US government agencies, but it's often difficult to work with. PUDL takes the original spreadsheets, CSV files, and databases and turns them into a unified resource. This allows users to spend more time on novel analysis and less time on data preparation.

The project is focused on serving researchers, activists, journalists, policy makers, and small businesses that might not otherwise be able to afford access to this data from commercial sources and who may not have the time or expertise to do all the data processing themselves from scratch.

We want to make this data accessible and easy to work with for as wide an audience as possible: anyone from a grassroots youth climate organizers working with Google sheets to university researchers with access to scalable cloud computing resources and everyone in between!

PUDL is comprised of three core components:

Raw Data Archives

PUDL archives all our raw inputs on Zenodo to ensure permanent, versioned access to the data. In the event that an agency changes how they publish data or deletes old files, the data processing pipeline will still have access to the original inputs. Each of the data inputs may have several different versions archived, and all are assigned a unique DOI (digital object identifier) and made available through Zenodo's REST API. You can read more about the Raw Data Archives in the docs.

Data Pipeline

The data pipeline (this repo) ingests raw data from the archives, cleans and integrates it, and writes the resulting tables to SQLite and Apache Parquet files, with some acompanying metadata stored as JSON. Each release of the PUDL software contains a set of of DOIs indicating which versions of the raw inputs it processes. This helps ensure that the outputs are replicable. You can read more about our ETL (extract, transform, load) process in the PUDL documentation.

Data Warehouse

The SQLite, Parquet, and JSON outputs from the data pipeline, sometimes called "PUDL outputs", are updated each night by an automated build process, and periodically archived so that users can access the data without having to install and run our data processing system. These outputs contain hundreds of tables and comprise a small file-based data warehouse that can be used for a variety of energy system analyses. Learn more about how to access the PUDL data.

What data is available?

PUDL currently integrates data from:

Thanks to support from the Alfred P. Sloan Foundation Energy & Environment Program, from 2021 to 2024 we will be cleaning and integrating the following data as well:

How do I access the data?

For details on how to access PUDL data, see the data access documentation. A quick summary:

Contributing to PUDL

Find PUDL useful? Want to help make it better? There are lots of ways to help!

Licensing

In general, our code, data, and other work are permissively licensed for use by anybody, for any purpose, so long as you give us credit for the work we've done.

Contact Us

About Catalyst Cooperative

Catalyst Cooperative is a small group of data wranglers and policy wonks organized as a worker-owned cooperative consultancy. Our goal is a more just, livable, and sustainable world. We integrate public data and perform custom analyses to inform public policy (Hire us!). Our focus is primarily on mitigating climate change and improving electric utility regulation in the United States.

pudl's People

Contributors

aesharpe avatar alanawlsn avatar apptrain avatar arengel avatar bendnorman avatar cmgosnell avatar davidmudrauskas avatar dependabot[bot] avatar dstansby avatar e-belfer avatar ezwelty avatar grgmiller avatar gschivley avatar jdangerx avatar karldw avatar katherinelamb avatar katie-lamb avatar knordback avatar pre-commit-ci[bot] avatar ptvirgo avatar pudlbot avatar robertozanchi avatar rousik avatar stevenbwinter avatar swinter2011 avatar trentonbush avatar wheelspawn avatar yashkumar1803 avatar zaneselvans avatar zschira avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pudl's Issues

Functionalize the operations taking place within pudl.init_db()

The pudl.init_db() subroutine is getting too long and has become unreadable. Separate various logical pieces of it into functions that define particular portions of the process, including:

  • importing the static tables/lists
  • generating and importing the "glue" tables.
  • the import & cleanup for each of the ferc1 tables.

This will make it easier to hand off & test the individual tasks of importing new ferc1 tables.

Assess impacts of constraints applied to plants for ID mapping

The constraints set on pulling the plants for the id mapping (ex. excluding anything under 5 MW) excluded some fields like common plants, which have expenses associated with them, but no capacity. Not a top priority by any means, but eventually we should go back through these constraints to see what we missed.

Example: for the f1_hydro table, we lost respondent_id, plant_names:
122, 'Common Hydro Plant'; 70, 'Common Facilities'

Spot check past FERC Form 1 versions to match line numbers with FERC Accounts

Periodically FERC updates their uniform chart of accounts for electric plant (e.g. they just recently added accounts for electricity storage devices, yay!). When this happens, the FERC Form 1 line numbers that correspond to a given FERC account may change. If that happens, all of our parsing of the f1_plant_in_srvce data will get messed up.

Somebody needs to go back and spot check some past years (between 2004 and 2015) to figure out if/when the lines-to-accounts mapping has changed in the past, and we'll need to generate a new mapping for each different set of lines/accounts. This could be done with old blank copies of Form 1 (maybe we can ask FERC?) or from the archived versions of the form that we got generated for PSCo. The page(s) we're interested in are FERC Form 1 pp 204-207.

For reference, the line-to-account mapping for 2015 is defined in a DataFrame named: pudl.constants.ferc_electric_plant_accounts

Devise naming convention for PUDL DB table columns

Many of the database tables we are creating have dozens of columns. We need readable, memorable, tab-completable convention for naming them. This could be based on the table or data source they are being imported from, and also the nature of the data within them.

Create Utility-Plant Relations

We need a table that indicates which plants are associated with what utilities. For now it can just contain two columns: utility_id and plant_id, both of which are primary keys, and foreign keys. The same table might later also store the ownership percentages.

Define string cleaning dictionaries for f1_steam fields

The f1_steam table in the ferc1 database has at least two freeform fields that need to be cleaned up. They are type_const and plant_kind. Export a list of all unique strings found in those two fields, from all of the data we can import into the database simultaneously -- years 2004-2015. Using whatever information you can find about what those fields are supposed to describe (e.g. the blank FERC Form 1 document, and the instructions for filling it out) categorize the strings into a few meaningful categories, using the ferc1_fuel_strings and ferc1_fuel_unit_strings dictionary-of-lists in constants.py as a model. Look at whatever other fields you need to within the f1_steam table for context on what is meant by the type_const and plant_kind fields. This issue is complete when there are ferc1_type_const and ferc1_plant_kind dictionaries in constants.py that can be used to clean up these columns.

Import f1_fuel data into PUDL database

Get at least the f1_fuel data automatically flowing into the PUDL database when init_db() is run. This will require cleaning up any data fields which are freeform strings (fuel, fuel_unit), deciding which records are so bad that they can't be imported, and ensuring that the necessary foreign key tables are consistent with the actual contents of the f1_fuel table.

Allow multiple years of data in ferc1 database

The ferc1 module can now pull in data from the old DBF files from 2004-2015, however, the database can only hold one year's worth of data at a time, because the non-data tables (like f1_respondents) don't have a year field, and so entries for the same respondents from different years collide in the database -- you can't add respondent_id 134 to the table more than once. There needs to be logic incorporated that allows the union of all respondent_id's and respondent_names to be added to f1_respondent, and something similar for other non-data tables.

Change FERC Form 1 DB ingestion to allow selection of year

Rather than hard-coding the year 2015 into the database ingestion, the user should be able to specify what year's data they want to pull in (or potentially which years they want to pull in?) and have that data get pulled. This will almost certainly involve some more grungy data cleaning, as new and exciting freeform strings describing fuels etc. will appear in previous years' data.

Flesh out static tables needed for EIA923

There are many static tables (e.g. abbreviations of NERC regions) that we should have available as foreign keys within the PUDL Database. They are summarized in the back of the EIA923 spreadsheet. Because they're simple, they'll also provide a good practice run for defining tables using the ORM, and getting those tables populated when init_db() runs.

Add an admin hours layer to the budget

Conservative estimate preferred by Alana
-Breaking up by task
-End of year - more heavy there - running payroll, team management with meetings, running invoices, running invoices

  • Beginning of year - heavier with set up

Devise naming convention for shared constants

The constants.py module is accumulating a lot of values, which pertain to different parts of the project, some of which contain the same kind of information but from different sources. We need a well defined naming convention so that we don't end up using the wrong values.

Define DB Table & Ingest function for f1_accumdepr_prvsn

Alongside the f1_plant_in_srvce table which describes the balances and changes in the electric plant in service, we need to ingest information about utility-wide depreciation, which comes from p. 219 of FERC Form 1, and is stored in table f1_accumdepr_prvsn. We need to define a PUDL DB table for this data, and write an ingest function. It appears similar in structure to f1_plant_in_srvce, which means we'll need to do a line number -> meaningful description dictionary/data table too, and hope that they don't change from year to year.

Pull EIA and FERC fuel data into the PUDL DB

Create the necessary tables in the PUDL DB to hold both FERC Form 1 annual fuel information (from the f1_fuel table) and EIA923 monthly fuel deliveries. Demonstrate the ability to populate these tables with information from FERC Form 1 and EIA923.

Test ingestion of FERC1 tables into PUDL for full 2004-2015 date range

Many FERC1 data tables are now successfully importing into PUDL, but only for the year 2015. Once we have the glue tables updated with relationships between plants and utilities for the years 2004-2015 (See Issue #26 ), we'll need to revisit the imports of all of the other years of these older tables, and make sure they still work.

Define PUDL DB table and import logic for f1_pumped_storage table

The ferc1 database has a table called f1_pumped_storage which stores attributes of various pumped hydro storage plants around the US. It's the simplest of the tables describing plants. Define a table to receive this data using the ORM in models_ferc1.py. Look at the FuelFERC1 class as a template.

Then create a function in pudl.py that pulls the f1_pumped_hydro data out of the ferc1 database into a DataFrame using pd.read_sql(), cleans it up as necessary for insertion into the PUDL DB, and adds it using DataFrame.to_sql(). Look at how the same work is done by for importing the f1_fuel data as an example.

When this issue is complete, pudl.init_db() should successfully import the pumped_hydro data.

Technical milestone map

As we finally approach having our initially desired data pulled into PUDL from FERC1 & EIA923 we need to have a full list of the issues required to do an initial alpha release (yay!) of PUDL that can be used to do interesting things in the world... like make some plots for potential funders to ogle.

Define DB table and ingest function for f1_hydro

Get the f1_hydro table imported into PUDL from FERC1 a process similar to that for the f1_steam and f1_pumped_storage to define the database table using the ORM in models_ferc1.py and a corresponding ingest function within pudl.py

EIA data normalization

Create schemata for the PUDL database tables which we will import the EIA923 data into, using the ORM syntax.

Devise naming convention for SQLAlchemy ORM Classes.

We need a readable, easily rememberable convention for the names of the classes which we are constructing with the SQLAlchemy ORM. This should determine the name of the class, and the name of the DB table which objects of this class will be records within.

Expand ID Mapping to data from 2006-2016 for FERC1 & EIA923

We can pull in FERC Form 1 data from 2004 onward. However, the id mapping "glue" tables that we have right now only encompass information from the 2015 FERC database. If we want to be able to work with multiple years of FERC data in the PUDL database, we need glue for those other years. Thus, the id mapping exercise needs to be expanded to pull in new associations between plants & utilities from prior FERC years.

If @cmgosnell & @swinter2011 can indicate which fields they need from the various plants tables to do the mapping, @zaneselvans can pull them from the 2004-2015 Form 1 DB for matching. If we can come up with a common set of columns for all the different types of plants, we could do it all in one go maybe?

finish quickbooks setup

  • create initial categories
  • create member accounts
  • create stock ledger
  • run the above by the accountant
  • anything else needed?

Investigate less zealous removal of NA values during f1_fuel import

After the fuel and fuel_unit strings are cleaned up in the f1_fuel import, any record which contains any NA values is dropped, before the DataFrame is pulled into the PUDL DB. In some cases, this means we lose some data. E.g. some utilities only report their mmbtu/kWh numbers on a separate "Total" line. We should check and see whether there's a less destructive way we can deal with these leftover records.

create classes for eia923 dictionaries

check to see if all metadata-type variables in models_eia923 have an associated dictionary in constants.py; once there are dictionaries create classes in models.py;
for new static constants added in models.py, add to ingest_static_tables function in pudl.py.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.