| Title: | US State Energy-Economy Panels with Renewable Portfolio Standards |
|---|---|
| Description: | Builds a documented, reproducible state-by-year panel for the 50 US states and the District of Columbia that combines energy consumption, prices and production from the US Energy Information Administration (EIA) State Energy Data System, electricity generation and retail sales, state energy-related carbon dioxide emissions, and state GDP, income and population from the Bureau of Economic Analysis (BEA). Data are downloaded on demand through the official APIs and cached locally, with the source, vintage and transformation of every variable recorded in a codebook. Renewable Portfolio Standard (RPS) rules are turned into standardised annual stringency indices (adoption, nominal, coverage-adjusted and incremental requirements, following Yin and Powers (2010) <doi:10.1016/j.enpol.2009.10.067>, plus design-flexibility indicators). Output works directly with the 'plm', 'fixest' and 'csdm' packages. |
| Authors: | Moses Adebayo [aut, cre, cph] |
| Maintainer: | Moses Adebayo <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-10-19 20:10:54 UTC |
| Source: | https://github.com/adebayomoses/rpspanel |
Prepares a panel for plm, fixest or csdm. The package does not
re-implement estimators; it hands a correctly indexed panel to them.
as_pdata(x, to = c("plm", "fixest", "csdm", "data.frame"))as_pdata(x, to = c("plm", "fixest", "csdm", "data.frame"))
x |
An |
to |
Target package. |
"plm": a pdata.frame indexed by state and year.
"fixest": a fixest_panel (for lag and lead operators) indexed by
state and year.
"csdm": a plain data frame sorted by state and year, with state
as a factor; pass id = "state" and time = "year" to csdm.
"data.frame": the same sorted plain data frame.
An object of the requested class.
p <- build_panel(states = c("CA", "TX"), years = 2005:2020, groups = "rps", rps_methods = c("adoption", "nominal")) head(as_pdata(p, "data.frame")) if (requireNamespace("plm", quietly = TRUE)) { class(as_pdata(p, "plm")) }p <- build_panel(states = c("CA", "TX"), years = 2005:2020, groups = "rps", rps_methods = c("adoption", "nominal")) head(as_pdata(p, "data.frame")) if (requireNamespace("plm", quietly = TRUE)) { class(as_pdata(p, "plm")) }
The main entry point of the package. Downloads (or reads from the cache) the requested EIA and BEA series, harmonises state codes and units, merges them into one tidy state-by-year table, adds derived variables and RPS stringency measures, and records the source and vintage of every variable.
build_panel( states = NULL, years = 2001:2022, vars = NULL, groups = panel_groups, rps_methods = c("adoption", "nominal", "coverage_adjusted", "incremental", "flexibility"), rps_rules = NULL, price_base_year = 2017, eia_key = NULL, bea_key = NULL, cache = TRUE, refresh = FALSE, quiet = FALSE, ... )build_panel( states = NULL, years = 2001:2022, vars = NULL, groups = panel_groups, rps_methods = c("adoption", "nominal", "coverage_adjusted", "incremental", "flexibility"), rps_rules = NULL, price_base_year = 2017, eia_key = NULL, bea_key = NULL, cache = TRUE, refresh = FALSE, quiet = FALSE, ... )
states |
States to include (any form accepted by
|
years |
Years to include. |
vars |
Variable names to include (see |
groups |
Variable groups to include when |
rps_methods |
Methods passed to |
rps_rules |
An |
price_base_year |
Base year for real prices. |
eia_key, bea_key
|
API keys; default to the |
cache, refresh
|
Use the download cache / force a fresh download. |
quiet |
Suppress progress messages. |
... |
Further arguments to |
If one source cannot be reached (no API key, no internet, service down) its variables are left out with a warning and the rest of the panel is still returned.
A data frame of class rps_panel with one row per state and year,
columns state, state_name, fips, year and the requested
variables. Attributes: sources (source, vintage, URL), codebook
(definitions of the included variables) and call.
# RPS measures only: no API key needed p <- build_panel(states = c("CA", "TX", "NY"), years = 2000:2025, groups = "rps", rps_methods = c("adoption", "nominal", "flexibility")) head(p) p <- build_panel(years = 2005:2022) codebook(p)# RPS measures only: no API key needed p <- build_panel(states = c("CA", "TX", "NY"), years = 2000:2025, groups = "rps", rps_methods = c("adoption", "nominal", "flexibility")) head(p) p <- build_panel(years = 2005:2022) codebook(p)
Downloads are cached as .rds files so that a panel can be rebuilt
offline and so that a data vintage stays pinned until you refresh it.
rps_cache_dir() returns the cache directory, rps_cache_list() lists
cached downloads and rps_cache_clear() deletes them.
rps_cache_dir() rps_cache_list() rps_cache_clear()rps_cache_dir() rps_cache_list() rps_cache_clear()
The cache directory defaults to tools::R_user_dir("rpspanel", "cache")
and can be changed with options(rpspanel.cache_dir = "path").
rps_cache_dir(): a path. rps_cache_list(): a data frame with
file, source, retrieved and size_kb. rps_cache_clear(): the
number of files removed, invisibly.
rps_cache_dir()rps_cache_dir()
Lists the citation for every source used in a panel, including the retrieval date (vintage), plus the citation for the package itself.
cite_sources(x = NULL, format = c("text", "bibtex"))cite_sources(x = NULL, format = c("text", "bibtex"))
x |
An |
format |
|
A character vector of references of class rps_citation, which
prints one reference per paragraph.
cite_sources(c("eia_seds", "bea_regional")) p <- build_panel(states = "CA", years = 2010:2020, groups = "rps", rps_methods = "nominal") cite_sources(p, format = "bibtex")cite_sources(c("eia_seds", "bea_regional")) p <- build_panel(states = "CA", years = 2010:2020, groups = "rps", rps_methods = "nominal") cite_sources(p, format = "bibtex")
Returns the definition, unit, source, source series identifier and
transformation of every variable the package can produce, or of the
variables in a panel built with build_panel().
codebook(x = NULL, group = NULL)codebook(x = NULL, group = NULL)
x |
|
group |
Optional group filter: |
A data frame with columns variable, group, label, unit,
source, series and transformation.
codebook(group = "rps") codebook(c("co2_pc", "gdp_real"))codebook(group = "rps") codebook(c("co2_pc", "gdp_real"))
Converts energy, mass, money-scale and population units used by EIA and BEA. Electricity is converted to Btu at the thermal equivalent of 3,412.14 Btu per kWh (the convention used in SEDS for electricity consumption).
convert_units(x, from, to) convert_units_available()convert_units(x, from, to) convert_units_available()
x |
Numeric vector. |
from, to
|
Unit names (case-insensitive), for example
|
Numeric vector in the to unit.
convert_units(1, "trillion Btu", "billion Btu") convert_units(1000, "thousand MWh", "TWh") convert_units(1, "million metric tons", "short ton")convert_units(1, "trillion Btu", "billion Btu") convert_units(1000, "thousand MWh", "TWh") convert_units(1, "million metric tons", "short ton")
Divides by a price index and rescales so that values are expressed in
prices of base_year.
deflate( x, price_index, years = NULL, base_year = NULL, index_years = years, index_values = price_index )deflate( x, price_index, years = NULL, base_year = NULL, index_years = years, index_values = price_index )
x |
Numeric vector of nominal values. |
price_index |
Price index for the same observations as |
years |
Optional years of the observations; needed with |
base_year |
Year whose prices the result is expressed in. If |
index_years, index_values
|
Optional full index series used to look up
the base-year value when |
Numeric vector of real values.
# $10 in 2010 and $12 in 2020 with deflator 90 and 110 (2017 = 100) deflate(c(10, 12), c(90, 110)) # Expressed in 2020 prices instead deflate(c(10, 12), c(90, 110), years = c(2010, 2020), base_year = 2020)# $10 in 2010 and $12 in 2020 with deflator 90 and 110 (2017 = 100) deflate(c(10, 12), c(90, 110)) # Expressed in 2020 prices instead deflate(c(10, 12), c(90, 110), years = c(2010, 2020), base_year = 2020)
Writes the panel and, by default, its codebook next to it
(<name>_codebook.csv). Stata files carry variable labels from the
codebook.
export_panel(x, path, format = NULL, codebook = TRUE)export_panel(x, path, format = NULL, codebook = TRUE)
x |
An |
path |
Output file path. |
format |
|
codebook |
Also write the codebook as CSV. |
The path, invisibly.
p <- build_panel(states = "CA", years = 2010:2020, groups = "rps", rps_methods = "nominal") f <- tempfile(fileext = ".csv") export_panel(p, f) head(read.csv(f))p <- build_panel(states = "CA", years = 2010:2020, groups = "rps", rps_methods = "nominal") f <- tempfile(fileext = ".csv") export_panel(p, f) head(read.csv(f))
Retrieves state series from the Bureau of Economic Analysis Regional accounts, or national series from the NIPA tables (used for price deflators).
fetch_bea( table, line_code, dataset = c("Regional", "NIPA"), states = NULL, years = NULL, api_key = NULL, cache = TRUE, refresh = FALSE )fetch_bea( table, line_code, dataset = c("Regional", "NIPA"), states = NULL, years = NULL, api_key = NULL, cache = TRUE, refresh = FALSE )
table |
BEA table name, for example |
line_code |
Line code (Regional) or line number (NIPA). |
dataset |
|
states |
States to keep (Regional only); |
years |
Years to keep; |
api_key |
BEA API key. Defaults to the |
cache |
Use the local download cache. |
refresh |
Ignore any cached copy and download again. |
Useful Regional tables and line codes:
SAGDP9 line 1: real GDP, all industries (millions of chained 2017
dollars); line 12: manufacturing.
SAGDP2 line 1: nominal GDP (millions of current dollars).
SAINC1 line 1: personal income (millions of dollars); line 2:
population (persons); line 3: per capita personal income (dollars).
Useful NIPA table: T10109 line 1, the implicit price deflator for GDP
(index, 2017 = 100).
A data frame with columns state (NA for NIPA data), year,
series ("<table>:<line>"), value and unit. Values are in the
units reported by BEA (the UNIT_MULT scale factor is already applied
to the unit label, not the value).
fetch_bea("SAGDP9", 1, states = "CA", years = 2015:2020) fetch_bea("T10109", 1, dataset = "NIPA")fetch_bea("SAGDP9", 1, states = "CA", years = 2015:2020) fetch_bea("T10109", 1, dataset = "NIPA")
Retrieves a state-level variable from the American Community Survey
1-year estimates (default: total population, B01003_001E). This is an
optional supplement: build_panel() takes population from BEA, which is
available for every year. ACS 1-year estimates start in 2005, and the
standard 2020 release does not exist, so that year is skipped.
fetch_census( years, variable = "B01003_001E", states = NULL, api_key = NULL, cache = TRUE, refresh = FALSE )fetch_census( years, variable = "B01003_001E", states = NULL, api_key = NULL, cache = TRUE, refresh = FALSE )
years |
Years to download (2005 onward). |
variable |
ACS variable code. |
states |
States to download; any form accepted by
|
api_key |
Census API key. Defaults to the |
cache |
Use the local download cache. |
refresh |
Ignore any cached copy and download again. |
A data frame with columns state, year, series, value and
unit ("persons" for the default population variable, otherwise NA;
look up other ACS variables in the Census documentation). Years that
fail to download are skipped with a warning.
fetch_census(2019, states = c("CA", "TX"))fetch_census(2019, states = c("CA", "TX"))
Queries version 2 of the US Energy Information Administration API and
returns tidy long data. Results are cached (see rps_cache_dir()); the
API key is never written to the cache.
fetch_eia( dataset = c("seds", "co2", "generation", "retail_sales"), series, states = NULL, years = NULL, api_key = NULL, cache = TRUE, refresh = FALSE )fetch_eia( dataset = c("seds", "co2", "generation", "retail_sales"), series, states = NULL, years = NULL, api_key = NULL, cache = TRUE, refresh = FALSE )
dataset |
One of |
series |
Character vector of series identifiers (see Details). |
states |
States to download; any form accepted by
|
years |
Integer vector of years. |
api_key |
EIA API key. Defaults to the |
cache |
Use the local download cache. |
refresh |
Ignore any cached copy and download again. |
Supported datasets:
"seds": State Energy Data System. series are SEDS MSN codes, for
example "TETCB" (total energy consumption, billion Btu).
"co2": energy-related CO2 emissions aggregates for all fuels.
series are EIA sector ids: "TT" (total), "EC" (electric power),
"IC" (industrial), "TC" (transportation), "RC" (residential),
"CC" (commercial).
"generation": net generation, all sectors (forms EIA-923/906/920).
series are fuel type ids such as "ALL", "COW", "NG", "NUC",
"HYC", "WND", "SUN", "GEO", "WWW", "WAS".
"retail_sales": electricity retail sales and average price, all
sectors. series are "sales" and/or "price".
A data frame with columns state, year, series, value and
unit, with attributes rps_source and rps_retrieved (download time,
UTC).
fetch_eia("seds", "TETCB", states = c("CA", "TX"), years = 2015:2020)fetch_eia("seds", "TETCB", states = c("CA", "TX"), years = 2015:2020)
Without arguments, returns the bundled coding (same as rps_rules()).
With URLs, downloads CSV files that follow the rps_rules() layout, for
example a shared or corrected version of the coding, and caches them.
The package does not redistribute DSIRE, LBNL or PUDL data; if you build
your own coding from those sources, check their terms of use.
fetch_rps(rules_url = NULL, targets_url = NULL, cache = TRUE, refresh = FALSE)fetch_rps(rules_url = NULL, targets_url = NULL, cache = TRUE, refresh = FALSE)
rules_url, targets_url
|
URLs (or local paths) of CSV files. |
cache |
Use the local download cache. |
refresh |
Ignore any cached copy and download again. |
An rps_rules object.
fetch_rps()fetch_rps()
Converts state names, USPS abbreviations or FIPS codes (two-digit, numeric,
or five-digit BEA GeoFips such as "06000") to a single representation.
Matching ignores case, surrounding white space and trailing footnote
markers such as the asterisks BEA appends to some state names.
harmonise_states(x, to = c("abbr", "name", "fips"), warn = TRUE)harmonise_states(x, to = c("abbr", "name", "fips"), warn = TRUE)
x |
A character or numeric vector of state identifiers. |
to |
Output representation: |
warn |
If |
A character vector the same length as x.
harmonise_states(c("California", "tx", "06", 36, "11000", "Alaska *")) harmonise_states(c("CA", "NY"), to = "fips")harmonise_states(c("California", "tx", "06", 36, "11000", "Alaska *")) harmonise_states(c("CA", "NY"), to = "fips")
Reads the RPS rule coding that feeds rps_stringency(). By default this is
the coding bundled with the package in inst/extdata/; you can point to
your own files with the same layout to correct or extend it.
rps_rules(states = NULL, rules_path = NULL, targets_path = NULL)rps_rules(states = NULL, rules_path = NULL, targets_path = NULL)
states |
Optional states to keep. |
rules_path, targets_path
|
Paths to CSV files with your own coding. Default: the files bundled with the package. |
The coding has two tables:
rules (one row per state): has_rps (1 = mandatory RPS, 0 = none),
enacted_year, first_compliance_year, repeal_year, target_type
("share" of retail sales, or "capacity_mw"), final_target,
final_target_year, coverage_share (share of retail sales covered),
out_of_state_rec, carveout, acp (0/1 design indicators),
carveout_types, acp_usd_mwh, baseline_re_share (optional existing
renewable share at enactment; filled from data by build_panel()),
source, verified and notes. Optional: baseline_includes_hydro
(1 if the targets count existing hydro, so the incremental baseline should
too; default 0).
targets (one row per legal target): state, year, target (share
of sales between 0 and 1, or MW for capacity targets).
States that do not appear in the rules table are treated as not yet
coded, and their stringency measures are NA rather than zero.
An object of class rps_rules: a list with data frames rules
and targets.
The bundled coding covers all 50 states and DC. Rows with
verified = TRUE have been hand-checked against the statute, the DSIRE
program page and the LBNL RPS & CES data, as set out in the package's
validation plan; source and notes give the citations and coding
choices. Please report corrections on the issue tracker.
r <- rps_rules() r head(r$targets)r <- rps_rules() r head(r$targets)
Turns coded RPS rules (rps_rules()) into comparable state-year measures,
so you can study how strong a policy is, not only whether it exists.
rps_stringency( years, states = NULL, method = c("adoption", "nominal", "coverage_adjusted", "incremental", "flexibility"), rules = rps_rules(), baseline = NULL, interpolation = c("linear", "step"), adopt_from = c("enactment", "first_compliance"), floor_zero = FALSE, sales = NULL, capacity_factor = 0.33 )rps_stringency( years, states = NULL, method = c("adoption", "nominal", "coverage_adjusted", "incremental", "flexibility"), rules = rps_rules(), baseline = NULL, interpolation = c("linear", "step"), adopt_from = c("enactment", "first_compliance"), floor_zero = FALSE, sales = NULL, capacity_factor = 0.33 )
years |
Years to compute. |
states |
States to include (default: all 50 + DC). |
method |
One or more of |
rules |
An |
baseline |
Optional data frame with columns |
interpolation |
|
adopt_from |
Year from which |
floor_zero |
If |
sales |
Optional data frame with columns |
capacity_factor |
Assumed capacity factor of the resources that meet a capacity-based standard. The default 0.33 is typical of wind, which met most of the Texas and Iowa requirements. |
Methods:
adoption: 1 if an RPS is in force that year (from adopt_from until
any repeal), else 0.
nominal: required renewable share of retail sales in that year.
Zero before the first compliance year. Between legal targets the
requirement is interpolated linearly (interpolation = "linear") or held
at the last legal target ("step"); after the final target year it is
held constant. If the first coded target lies after the enactment year,
linear interpolation starts from zero at enactment. Capacity-based (MW)
standards (Texas, Iowa) are converted to an equivalent share of covered
sales: MW * capacity_factor * 8.76 / (sales_gwh * coverage_share),
the same approach Berkeley Lab uses. This needs sales; without it they
are NA.
coverage_adjusted: nominal requirement times the share of retail sales
covered by the standard.
incremental: requirement beyond the renewable share the state already
had at enactment, following Yin and Powers (2010):
nominal * coverage - baseline_share while the nominal requirement is
positive, otherwise 0. The baseline is taken from baseline, or from
the baseline_re_share column of the rules. Also returns the baseline
used (rps_baseline_share). build_panel() measures the baseline the
same way the target is defined: including hydro for states whose targets
count existing hydro (baseline_includes_hydro = 1, New York),
excluding it otherwise.
flexibility: indicators for out-of-state renewable credits, carve-outs
and alternative compliance payments, set to 0 when no RPS is in force.
States missing from the rule coding get NA for every measure.
A data frame with state, year and the columns for each method:
rps_adoption, rps_nominal, rps_coverage_adj, rps_incremental,
rps_baseline_share, rps_oos_rec, rps_carveout, rps_acp.
Yin, H., & Powers, N. (2010). Do state renewable portfolio standards promote in-state renewable generation? Energy Policy, 38(2), 1140-1149.
s <- rps_stringency(2000:2030, states = c("CA", "WA", "TX", "FL"), method = c("adoption", "nominal")) s[s$state == "WA" & s$year %in% 2011:2021, ] # Capacity (MW) standards become shares when sales are supplied tx_sales <- data.frame(state = "TX", year = 2015, sales_gwh = 380000) rps_stringency(2015, "TX", method = "nominal", sales = tx_sales) # Step interpolation follows the legal schedule exactly rps_stringency(2012:2020, states = "WA", method = "nominal", interpolation = "step")s <- rps_stringency(2000:2030, states = c("CA", "WA", "TX", "FL"), method = c("adoption", "nominal")) s[s$state == "WA" & s$year %in% 2011:2021, ] # Capacity (MW) standards become shares when sales are supplied tx_sales <- data.frame(state = "TX", year = 2015, sales_gwh = 380000) rps_stringency(2015, "TX", method = "nominal", sales = tx_sales) # Step interpolation follows the legal schedule exactly rps_stringency(2012:2020, states = "WA", method = "nominal", interpolation = "step")
Returns the 51 geographic units covered by the package with their USPS abbreviation, name and two-digit FIPS code.
us_states()us_states()
A data frame with columns abbr, name and fips.
head(us_states())head(us_states())