EROITools
EROITools.Rmd
Introduction
The R
package EROITools
provides tools to
aggregate Energy Return On Investment (EROI) values previously
calculated using a Physical Supply Use Table (PSUT) framework to
represent the Energy Conversion Chain (see Heun,
Owen, and Brockway (2018)). Previous to using the
EROITools
package, the World Energy Extended Balances
(WEEB) from the International Energy Agency (IEA) can be loaded and
tidied using the IEATools
and ECCTools
R
packages. The Recca
R
package
then allows analysts to calculate a wide range of EROIs at the product
and industry levels, and the EROITools
package provides
tools aggregate the calculated EROIs by product group. Important
features of the EROITools
package include the
following:
- Aggregations can be performed either at the global or national level;
- Aggregations can be performed at both the primary and final stage of energy use, but also at the useful stage of energy use providing that final-to-useful efficiencies are provided by the analyst for each energy product;
- At the useful stage, the package also allows analysts to conduct these aggregations respecting sectoral or end-use breakdowns, so that the average useful stage EROI of a product group can be calculated for a given final demand sector (for instance steelmaking) or for a given end-use category (for instance high temperature heating);
- Last, the package allows analysts to add additional energy requirements (supposing that these are provided by the analyst) that cannot be quantified using the IEA’s WEEB such as supply chain energy requirements — see Brockway et al. (2019) or Brand-Correa et al. (2017) for examples of a quantification of such indirect energy flows.
Available vignettes
The vignettes available for this package detail how to conduct the following tasks:
- Aggregating EROIs by fossil fuel group: Shows how EROIs can be aggregated by fossil fuel group at the primary, final, and useful energy stages. The product-level EROIs need to have been calculated and extracted first as described in the subsequent example section.
- Breaking down useful stage EROIs by sector or end-use: Shows how to calculate useful stage EROIs while respecting a breakdown either by final demand sector or end-use category.
- Adding indirect or other energy requirements: Shows how indirect or other energy requirements can be added to the EROI calculations.
Example for vignettes: the AB world
We use the same example than the one used to describe the
ECCTools
package: welcome back to the fictitious AB world
(consisting of country A and country B)!
Tidy AB data
Let’s now have a look to the AB data organised in a
.tidy_iea_df
as provided by the ECCTools
package.
# Fix product-level balances within each country
ECCTools::tidy_AB_data %>%
dplyr::glimpse()
#> Rows: 102
#> Columns: 11
#> $ Country <chr> "A", "A", "A", "A", "A", "A", "A", "A", "A", "A…
#> $ Method <chr> "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "PCM"…
#> $ Energy.type <chr> "E", "E", "E", "E", "E", "E", "E", "E", "E", "E…
#> $ Last.stage <chr> "Final", "Final", "Final", "Final", "Final", "F…
#> $ Year <dbl> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018,…
#> $ Ledger.side <chr> "Consumption", "Consumption", "Consumption", "C…
#> $ Flow.aggregation.point <chr> "Industry", "Industry", "Industry", "Industry",…
#> $ Flow <chr> "Iron and steel", "Iron and steel", "Iron and s…
#> $ Product <chr> "Blast furnace gas", "Electricity", "Heat", "Ke…
#> $ Unit <chr> "ktoe", "ktoe", "ktoe", "ktoe", "ktoe", "ktoe",…
#> $ E.dot <dbl> 500, 2920, 50, 1750, 500, 365, 200, 120, 700, 2…
Calculation of product-level EROIs
Domestic Technology Assumption
Let us first modify the Energy Conversion Chain to make it compliant
with the Domestic Technology Assumption (see the vignettes of the
ECCTools
package for more information — the basic idea is
to avoid taking into consideration imports in the supply mix of a given
country).
# Transforming Energy Conversion Chain to Domestic Technology Assumption
tidy_AB_dta <- ECCTools::tidy_AB_data %>%
IEATools::add_psut_matnames() %>%
ECCTools::transform_to_dta(requirement_matrices_list = c("U_feed"),
select_dta_observations = FALSE) %>%
dplyr::glimpse()
#> Rows: 102
#> Columns: 12
#> $ Country <chr> "A", "A", "A", "A", "A", "A", "A", "A", "A", "A…
#> $ Method <chr> "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "PCM"…
#> $ Energy.type <chr> "E", "E", "E", "E", "E", "E", "E", "E", "E", "E…
#> $ Last.stage <chr> "Final", "Final", "Final", "Final", "Final", "F…
#> $ Year <dbl> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018,…
#> $ Ledger.side <chr> "Consumption", "Consumption", "Consumption", "C…
#> $ Flow.aggregation.point <chr> "Industry", "Industry", "Industry", "Industry",…
#> $ Flow <chr> "Iron and steel", "Iron and steel", "Iron and s…
#> $ Product <chr> "Blast furnace gas", "Electricity", "Heat", "Ke…
#> $ Unit <chr> "ktoe", "ktoe", "ktoe", "ktoe", "ktoe", "ktoe",…
#> $ E.dot <dbl> 500, 2920, 50, 1750, 500, 365, 200, 120, 700, 2…
#> $ matnames <chr> "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y", "Y…
Then, we construct the Input-Output matrices needed to conduct the calculations.
# Calculating associated Input-Output matrices
tidy_io_AB_dta <- tidy_AB_dta %>%
IEATools::prep_psut() %>%
Recca::calc_io_mats(method_q_calculation = "sum_R_V_cols") %>%
dplyr::glimpse()
#> Rows: 2
#> Columns: 34
#> $ Country <chr> "A", "B"
#> $ Method <chr> "PCM", "PCM"
#> $ Energy.type <chr> "E", "E"
#> $ Last.stage <chr> "Final", "Final"
#> $ Year <dbl> 2018, 2018
#> $ B <list> <matrix[1 x 1]>, <<matrix[3 x 3]>>
#> $ Y <list> <<matrix[9 x 6]>>, <<matrix[7 x 4]>>
#> $ S_units <list> <<matrix[12 x 1]>>, <<matrix[9 x 1]>>
#> $ R <list> <<matrix[3 x 3]>>, <<matrix[1 x 7]>>
#> $ U <list> <<matrix[11 x 7]>>, <<matrix[8 x 4]>>
#> $ U_feed <list> <<matrix[9 x 7]>>, <<matrix[5 x 4]>>
#> $ U_EIOU <list> <<matrix[5 x 7]>>, <<matrix[5 x 4]>>
#> $ r_EIOU <list> <<matrix[11 x 7]>>, <<matrix[8 x 4]>>
#> $ V <list> <<matrix[7 x 9]>>, <<matrix[4 x 6]>>
#> $ y <list> <<matrix[9 x 1]>>, <<matrix[7 x 1]>>
#> $ q <list> <<matrix[12 x 1]>>, <<matrix[7 x 1]>>
#> $ f <list> <<matrix[7 x 1]>>, <<matrix[4 x 1]>>
#> $ g <list> <<matrix[7 x 1]>>, <<matrix[4 x 1]>>
#> $ h <list> <<matrix[3 x 1]>>, <<matrix[7 x 1]>>
#> $ r <list> <<matrix[3 x 1]>>, <matrix[1 x 1]>
#> $ W <list> <<matrix[12 x 7]>>, <<matrix[9 x 4]>>
#> $ Z <list> <<matrix[11 x 7]>>, <<matrix[8 x 4]>>
#> $ K <list> <<matrix[11 x 7]>>, <<matrix[8 x 4]>>
#> $ C <list> <<matrix[9 x 7]>>, <<matrix[6 x 4]>>
#> $ D <list> <<matrix[7 x 12]>>, <<matrix[4 x 7]>>
#> $ A <list> <<matrix[11 x 12]>>, <<matrix[8 x 7]>>
#> $ O <list> <<matrix[3 x 3]>>, <<matrix[1 x 7]>>
#> $ L_pxp <list> <<matrix[12 x 12]>>, <<matrix[9 x 9]>>
#> $ L_ixp <list> <<matrix[7 x 12]>>, <<matrix[4 x 9]>>
#> $ Z_feed <list> <<matrix[9 x 7]>>, <<matrix[5 x 4]>>
#> $ K_feed <list> <<matrix[9 x 7]>>, <<matrix[5 x 4]>>
#> $ A_feed <list> <<matrix[9 x 12]>>, <<matrix[5 x 7]>>
#> $ L_pxp_feed <list> <<matrix[12 x 12]>>, <<matrix[9 x 9]>>
#> $ L_ixp_feed <list> <<matrix[7 x 12]>>, <<matrix[4 x 9]>>
Then, we calculate the product-level EROIs in a matrix format.
# Calculating EROI vectors (matrix format)
tidy_AB_erois_matrices_dta <- tidy_io_AB_dta %>%
Recca::calc_E_EIOU() %>%
Recca::calc_erois() %>%
dplyr::glimpse()
#> Rows: 2
#> Columns: 40
#> $ Country <chr> "A", "B"
#> $ Method <chr> "PCM", "PCM"
#> $ Energy.type <chr> "E", "E"
#> $ Last.stage <chr> "Final", "Final"
#> $ Year <dbl> 2018, 2018
#> $ B <list> <matrix[1 x 1]>, <<matrix[3 x 3]>>
#> $ Y <list> <<matrix[9 x 6]>>, <<matrix[7 x 4]>>
#> $ S_units <list> <<matrix[12 x 1]>>, <<matrix[9 x 1]>>
#> $ R <list> <<matrix[3 x 3]>>, <<matrix[1 x 7]>>
#> $ U <list> <<matrix[11 x 7]>>, <<matrix[8 x 4]>>
#> $ U_feed <list> <<matrix[9 x 7]>>, <<matrix[5 x 4]>>
#> $ U_EIOU <list> <<matrix[5 x 7]>>, <<matrix[5 x 4]>>
#> $ r_EIOU <list> <<matrix[11 x 7]>>, <<matrix[8 x 4]>>
#> $ V <list> <<matrix[7 x 9]>>, <<matrix[4 x 6]>>
#> $ y <list> <<matrix[9 x 1]>>, <<matrix[7 x 1]>>
#> $ q <list> <<matrix[12 x 1]>>, <<matrix[7 x 1]>>
#> $ f <list> <<matrix[7 x 1]>>, <<matrix[4 x 1]>>
#> $ g <list> <<matrix[7 x 1]>>, <<matrix[4 x 1]>>
#> $ h <list> <<matrix[3 x 1]>>, <<matrix[7 x 1]>>
#> $ r <list> <<matrix[3 x 1]>>, <matrix[1 x 1]>
#> $ W <list> <<matrix[12 x 7]>>, <<matrix[9 x 4]>>
#> $ Z <list> <<matrix[11 x 7]>>, <<matrix[8 x 4]>>
#> $ K <list> <<matrix[11 x 7]>>, <<matrix[8 x 4]>>
#> $ C <list> <<matrix[9 x 7]>>, <<matrix[6 x 4]>>
#> $ D <list> <<matrix[7 x 12]>>, <<matrix[4 x 7]>>
#> $ A <list> <<matrix[11 x 12]>>, <<matrix[8 x 7]>>
#> $ O <list> <<matrix[3 x 3]>>, <<matrix[1 x 7]>>
#> $ L_pxp <list> <<matrix[12 x 12]>>, <<matrix[9 x 9]>>
#> $ L_ixp <list> <<matrix[7 x 12]>>, <<matrix[4 x 9]>>
#> $ Z_feed <list> <<matrix[9 x 7]>>, <<matrix[5 x 4]>>
#> $ K_feed <list> <<matrix[9 x 7]>>, <<matrix[5 x 4]>>
#> $ A_feed <list> <<matrix[9 x 12]>>, <<matrix[5 x 7]>>
#> $ L_pxp_feed <list> <<matrix[12 x 12]>>, <<matrix[9 x 9]>>
#> $ L_ixp_feed <list> <<matrix[7 x 12]>>, <<matrix[4 x 9]>>
#> $ E_EIOU <list> <<matrix[5 x 7]>>, <<matrix[5 x 4]>>
#> $ e_EIOU <list> <<matrix[7 x 1]>>, <<matrix[4 x 1]>>
#> $ eroi_g_p <list> <<matrix[12 x 1]>>, <<matrix[9 x 1]>>
#> $ eroi_g_i <list> <<matrix[7 x 1]>>, <<matrix[4 x 1]>>
#> $ eroi_g_p_feed <list> <<matrix[12 x 1]>>, <<matrix[9 x 1]>>
#> $ eroi_g_i_feed <list> <<matrix[7 x 1]>>, <<matrix[4 x 1]>>
Last, we can drop the matrix format and extract the product-level EROIs in a tidy data frame format.
# Extracting EROI values to a tidy data frame format
tidy_AB_erois_dta <- tidy_AB_erois_matrices_dta %>%
EROITools::extract_tidy_product_erois() %>%
dplyr::mutate(
Eroi.method = "DTA"
) %>%
dplyr::relocate(tidyselect::all_of("Eroi.method"), .after = Year) %>%
dplyr::glimpse()
#> Rows: 36
#> Columns: 10
#> $ Country <chr> "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A"…
#> $ Method <chr> "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "P…
#> $ Energy.type <chr> "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E"…
#> $ Last.stage <chr> "Final", "Final", "Final", "Final", "Final", "Final", "Fin…
#> $ Year <dbl> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018…
#> $ Eroi.method <chr> "DTA", "DTA", "DTA", "DTA", "DTA", "DTA", "DTA", "DTA", "D…
#> $ Type <chr> "Gross", "Gross", "Gross", "Gross", "Gross", "Gross", "Gro…
#> $ Boundary <chr> "All", "All", "All", "All", "All", "All", "All", "All", "A…
#> $ Product <chr> "Blast furnace gas", "Coke oven coke", "Coking coal", "Cru…
#> $ EROI <dbl> 5.185227, 7.239824, 91.083095, 33.935281, 26.362358, 19.07…
Global Market Assumption
Alternatively, we can modify the Energy Conversion Chain to describe energy flows across countries using a Multi-Regional Physical Supply Use Table framework (see Aramendia et al. (2022)). For the sake of simplicity, we use here the Global Market Assumption to demonstrate calculations with the multi-regional framework.
# Transforming Energy Conversion Chain to Global Market Assumption
tidy_AB_data_gma <- ECCTools::tidy_AB_data %>%
IEATools::add_psut_matnames() %>%
ECCTools::transform_to_gma() %>%
dplyr::glimpse()
#> Rows: 101
#> Columns: 12
#> $ Country <chr> "World", "World", "World", "World", "World", "W…
#> $ Method <chr> "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "PCM"…
#> $ Energy.type <chr> "E", "E", "E", "E", "E", "E", "E", "E", "E", "E…
#> $ Last.stage <chr> "Final", "Final", "Final", "Final", "Final", "F…
#> $ Year <dbl> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018,…
#> $ Ledger.side <chr> "Supply", "Supply", "Supply", "Supply", "Supply…
#> $ Flow.aggregation.point <chr> "Total primary energy supply", "Total primary e…
#> $ Flow <chr> "{A}_Resources [of Coking coal]", "{A}_Resource…
#> $ Product <chr> "{A}_Coking coal [from Resources]", "{A}_Crude …
#> $ Unit <chr> "ktoe", "ktoe", "ktoe", "ktoe", "ktoe", "ktoe",…
#> $ E.dot <dbl> 5000, 8500, 4000, 600, 2000, 3000, 2500, 850, 5…
#> $ matnames <chr> "R", "R", "R", "R", "R", "R", "R", "V", "V", "V…
Then, we construct the Input-Output matrices needed to conduct the calculations.
# Calculating associated Input-Output matrices
tidy_io_AB_gma <- tidy_AB_data_gma %>%
IEATools::prep_psut() %>%
Recca::calc_io_mats(method_q_calculation = "sum_R_V_cols") %>%
dplyr::glimpse()
#> Rows: 1
#> Columns: 33
#> $ Country <chr> "World"
#> $ Method <chr> "PCM"
#> $ Energy.type <chr> "E"
#> $ Last.stage <chr> "Final"
#> $ Year <dbl> 2018
#> $ Y <list> <<matrix[13 x 6]>>
#> $ S_units <list> <<matrix[21 x 1]>>
#> $ R <list> <<matrix[7 x 7]>>
#> $ U <list> <<matrix[16 x 11]>>
#> $ U_feed <list> <<matrix[11 x 11]>>
#> $ U_EIOU <list> <<matrix[9 x 11]>>
#> $ r_EIOU <list> <<matrix[16 x 11]>>
#> $ V <list> <<matrix[11 x 15]>>
#> $ y <list> <<matrix[13 x 1]>>
#> $ q <list> <<matrix[21 x 1]>>
#> $ f <list> <<matrix[11 x 1]>>
#> $ g <list> <<matrix[11 x 1]>>
#> $ h <list> <<matrix[7 x 1]>>
#> $ r <list> <<matrix[7 x 1]>>
#> $ W <list> <<matrix[18 x 11]>>
#> $ Z <list> <<matrix[16 x 11]>>
#> $ K <list> <<matrix[16 x 11]>>
#> $ C <list> <<matrix[15 x 11]>>
#> $ D <list> <<matrix[11 x 21]>>
#> $ A <list> <<matrix[16 x 21]>>
#> $ O <list> <<matrix[7 x 7]>>
#> $ L_pxp <list> <<matrix[21 x 21]>>
#> $ L_ixp <list> <<matrix[11 x 21]>>
#> $ Z_feed <list> <<matrix[11 x 11]>>
#> $ K_feed <list> <<matrix[11 x 11]>>
#> $ A_feed <list> <<matrix[11 x 21]>>
#> $ L_pxp_feed <list> <<matrix[21 x 21]>>
#> $ L_ixp_feed <list> <<matrix[11 x 21]>>
Then, we calculate the product-level EROIs in a matric format.
# Calculating EROI vectors (matrix format)
tidy_AB_erois_matrices_gma <- tidy_io_AB_gma %>%
Recca::calc_E_EIOU() %>%
Recca::calc_erois() %>%
dplyr::glimpse()
#> Rows: 1
#> Columns: 39
#> $ Country <chr> "World"
#> $ Method <chr> "PCM"
#> $ Energy.type <chr> "E"
#> $ Last.stage <chr> "Final"
#> $ Year <dbl> 2018
#> $ Y <list> <<matrix[13 x 6]>>
#> $ S_units <list> <<matrix[21 x 1]>>
#> $ R <list> <<matrix[7 x 7]>>
#> $ U <list> <<matrix[16 x 11]>>
#> $ U_feed <list> <<matrix[11 x 11]>>
#> $ U_EIOU <list> <<matrix[9 x 11]>>
#> $ r_EIOU <list> <<matrix[16 x 11]>>
#> $ V <list> <<matrix[11 x 15]>>
#> $ y <list> <<matrix[13 x 1]>>
#> $ q <list> <<matrix[21 x 1]>>
#> $ f <list> <<matrix[11 x 1]>>
#> $ g <list> <<matrix[11 x 1]>>
#> $ h <list> <<matrix[7 x 1]>>
#> $ r <list> <<matrix[7 x 1]>>
#> $ W <list> <<matrix[18 x 11]>>
#> $ Z <list> <<matrix[16 x 11]>>
#> $ K <list> <<matrix[16 x 11]>>
#> $ C <list> <<matrix[15 x 11]>>
#> $ D <list> <<matrix[11 x 21]>>
#> $ A <list> <<matrix[16 x 21]>>
#> $ O <list> <<matrix[7 x 7]>>
#> $ L_pxp <list> <<matrix[21 x 21]>>
#> $ L_ixp <list> <<matrix[11 x 21]>>
#> $ Z_feed <list> <<matrix[11 x 11]>>
#> $ K_feed <list> <<matrix[11 x 11]>>
#> $ A_feed <list> <<matrix[11 x 21]>>
#> $ L_pxp_feed <list> <<matrix[21 x 21]>>
#> $ L_ixp_feed <list> <<matrix[11 x 21]>>
#> $ E_EIOU <list> <<matrix[9 x 11]>>
#> $ e_EIOU <list> <<matrix[11 x 1]>>
#> $ eroi_g_p <list> <<matrix[21 x 1]>>
#> $ eroi_g_i <list> <<matrix[11 x 1]>>
#> $ eroi_g_p_feed <list> <<matrix[21 x 1]>>
#> $ eroi_g_i_feed <list> <<matrix[11 x 1]>>
Last, we can drop the matrix format and extract the product-level EROIs in a tidy data frame format.
# Extracting EROI values to a tidy data frame format
tidy_AB_erois_gma <- tidy_AB_erois_matrices_gma %>%
EROITools::extract_tidy_product_erois() %>%
dplyr::mutate(
Eroi.method = "GMA"
) %>%
dplyr::relocate(tidyselect::all_of("Eroi.method"), .after = Year) %>%
dplyr::glimpse()
#> Rows: 36
#> Columns: 10
#> $ Country <chr> "World", "World", "World", "World", "World", "World", "Wor…
#> $ Method <chr> "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "PCM", "P…
#> $ Energy.type <chr> "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E"…
#> $ Last.stage <chr> "Final", "Final", "Final", "Final", "Final", "Final", "Fin…
#> $ Year <dbl> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018…
#> $ Eroi.method <chr> "GMA", "GMA", "GMA", "GMA", "GMA", "GMA", "GMA", "GMA", "G…
#> $ Type <chr> "Gross", "Gross", "Gross", "Gross", "Gross", "Gross", "Gro…
#> $ Boundary <chr> "All", "All", "All", "All", "All", "All", "All", "All", "A…
#> $ Product <chr> "{A}_Blast furnace gas", "{A}_Coke oven coke", "{A}_Coking…
#> $ EROI <dbl> 3.231508, 16.660572, 89.065580, 33.838980, 24.019478, 18.0…
It can be seen that in the Global Market Assumption, there is only one region (“World”), and that the EROI of each product is specified in function of the region of production (not consumption!) of the product — information contained in the product name (“Product” column).
The rest of the vignettes will demonstrate the EROITools
package based on the tidy_AB_erois_dta
and
tidy_AB_erois_gma
data frames.