Skip to contents

Introduction

Recca is an R package that builds upon input-output (I-O) analysis, developed originally to analyze money flow through economies, to analyze energy conversion chains (ECCs). Historically, input-output (I-O) analysis has been used to analyze “what-if” scenarios involving changes to the production structure of an economy. A common scenario asks “how will the structure of intermediate industries (represented by \(\mathbf{U}\) and \(\mathbf{V}\) matrices) change when final demand (represented by the \(\mathbf{Y}\) matrix) changes?” In the economic arena, Leontief’s early work answered this question via a matrix inversion that now bears his name, the “Leontief inverse (\(\mathbf{L}\))” (Leontief 1941). Analysts with an I-O background will know the famous equation \(\mathbf{L} = (\mathbf{I} - \mathbf{A})^{-1}\).

The Recca package provides functions that perform several “what if” analyses for the analyst. Each function has the name new_*, where * indicates the changed matrix or portion of the ECC. Some functions have the suffix _ps to indicate the functions assume perfect substitution (ps) of industry inputs throughout the ECC. The new_* functions return the resource (\(\mathbf{R}\)), use (\(\mathbf{U}\)), make (\(\mathbf{V}\)), and final demand (\(\mathbf{Y}\)) matrices that would be present under the conditions given by arguments to the new_* functions. Arguments for new or changed versions of vectors or matrices are given the suffix _prime in the new_* functions. For example, the changed version of the use matrix (\(\mathbf{U}\)) is called U_prime.

For the examples that follow, we’ll use one ECC from the UKEnergy2000mats data frame which represents a portion of the primary and final energy flows through the UK in the year 2000.

library(dplyr)
library(magrittr)
library(matsbyname)
library(matsindf)
library(Recca)
library(tidyr)
OurECC <- UKEnergy2000mats %>% 
  dplyr::filter(Last.stage == "Final") %>% 
  tidyr::spread(key = "matrix.name", value = "matrix")
dplyr::glimpse(OurECC)
#> Rows: 1
#> Columns: 12
#> $ Country     <chr> "GBR"
#> $ Year        <dbl> 2000
#> $ Energy.type <chr> "E"
#> $ Last.stage  <chr> "Final"
#> $ R           <list> <<matrix[2 x 2]>>
#> $ r_EIOU      <list> <<matrix[12 x 9]>>
#> $ S_units     <list> <<matrix[12 x 1]>>
#> $ U           <list> <<matrix[12 x 9]>>
#> $ U_EIOU      <list> <<matrix[7 x 8]>>
#> $ U_feed      <list> <<matrix[9 x 9]>>
#> $ V           <list> <<matrix[9 x 10]>>
#> $ Y           <list> <<matrix[4 x 2]>>

After a short discussion of the inputs to the new_* functions, each type of analysis is described in turn.

Inputs to new_* functions

Inputs to the new_* functions include matrices that describe the ECC and matrices that describe the input-output structure of the ECC.

Matrices that describe the ECC

The new_* functions take as inputs resource (\(\mathbf{R}\)), use (\(\mathbf{U}\)), make (\(\mathbf{V}\)), and final demand (\(\mathbf{Y}\)) matrices that describe the ECC.

To look at the ECC, we can draw a Sankey diagram. A Sankey diagram for the first row of the UKEnergyMatsWithR data frame is given below.

make_sankey(OurECC) %>% 
  magrittr::extract2("Sankey") %>% # Extracts the "Sankey" column
  magrittr::extract2(1) # Extracts the first row of the "Sankey" column

Matrices that describe the input-output structure of the ECC

Each new_* function requires basic knowledge about the I-O structure of the ECCs in the form of named vectors and matrices. Thus, the first step in any “what-if” analysis is to calculate the input-output structure of the energy conversion chain. The calc_io_mats() function is the simplest way to obtain the necessary I-O structure, which appears as additional columns appended at the right of the OurECC data frame in our example. (The names of the additional columns are given by arguments to the calc_io_mats() function.)

IO_mats <- OurECC %>% 
  # Obtain the I-O structure of the ECCs
  calc_io_mats()
# Note additional columns appended to the data frame.
dplyr::glimpse(IO_mats)
#> Rows: 1
#> Columns: 32
#> $ Country     <chr> "GBR"
#> $ Year        <dbl> 2000
#> $ Energy.type <chr> "E"
#> $ Last.stage  <chr> "Final"
#> $ R           <list> <<matrix[2 x 2]>>
#> $ r_EIOU      <list> <<matrix[12 x 9]>>
#> $ S_units     <list> <<matrix[12 x 1]>>
#> $ U           <list> <<matrix[12 x 9]>>
#> $ U_EIOU      <list> <<matrix[7 x 8]>>
#> $ U_feed      <list> <<matrix[9 x 9]>>
#> $ V           <list> <<matrix[9 x 10]>>
#> $ Y           <list> <<matrix[4 x 2]>>
#> $ y           <list> <<matrix[4 x 1]>>
#> $ q           <list> <<matrix[12 x 1]>>
#> $ f           <list> <<matrix[9 x 1]>>
#> $ g           <list> <<matrix[9 x 1]>>
#> $ h           <list> <<matrix[2 x 1]>>
#> $ r           <list> <<matrix[2 x 1]>>
#> $ W           <list> <<matrix[12 x 9]>>
#> $ Z           <list> <<matrix[12 x 9]>>
#> $ K           <list> <<matrix[12 x 9]>>
#> $ C           <list> <<matrix[10 x 9]>>
#> $ D           <list> <<matrix[9 x 12]>>
#> $ A           <list> <<matrix[12 x 12]>>
#> $ O           <list> <<matrix[2 x 2]>>
#> $ L_pxp       <list> <<matrix[12 x 12]>>
#> $ L_ixp       <list> <<matrix[9 x 12]>>
#> $ Z_feed      <list> <<matrix[9 x 9]>>
#> $ K_feed      <list> <<matrix[9 x 9]>>
#> $ A_feed      <list> <<matrix[9 x 12]>>
#> $ L_pxp_feed  <list> <<matrix[12 x 12]>>
#> $ L_ixp_feed  <list> <<matrix[9 x 12]>>

With the I-O structure of the ECC determined (and represented by the \(\mathbf{q}\), \(\mathbf{f}\), \(\mathbf{h}\), \(\mathbf{r}\) and \(\mathbf{g}\) vectors and the \(\mathbf{W}\), \(\mathbf{Z}\), \(\mathbf{K}\), \(\mathbf{C}\), \(\mathbf{D}\), , \(\mathbf{A}\), \(\mathbf{L_{pxp}}\), and \(\mathbf{L_{ixp}}\) matrices), we can use the new_* functions to ask “what if” questions.

What if final demand changes? Function new_Y()

The classic I-O question is “what if final demand (\(\mathbf{Y}\)) changes?” Recca has a function for that: new_Y(). The new_Y() function looks upstream in the ECC to determine the effects of a change in final demand. To demonstrate, we’ll double the Residential final demand for electricity from the grid (Elect - Grid) in our ECC.

double <- function(x) {
  2*x
}

DoubleRes <- IO_mats %>% 
  mutate(
    Y_prime = matsbyname::elementapply_byname(double, a = Y, row = "Elect [from Grid]", col = "Residential")
  )
DoubleRes$Y[[1]]
#>                     Residential Transport
#> Diesel [from Dist.]           0     14750
#> Elect [from Grid]          6000         0
#> NG [from Dist.]           25000         0
#> Petrol [from Dist.]           0     26000
#> attr(,"rowtype")
#> [1] "Product"
#> attr(,"coltype")
#> [1] "Industry"
DoubleRes$Y_prime[[1]]
#>                     Residential Transport
#> Diesel [from Dist.]           0     14750
#> Elect [from Grid]         12000         0
#> NG [from Dist.]           25000         0
#> Petrol [from Dist.]           0     26000
#> attr(,"rowtype")
#> [1] "Product"
#> attr(,"coltype")
#> [1] "Industry"

Now we can use the new_Y() function to estimate the ECC with the larger final demand for residential electricity. The original Sankey diagram is:

make_sankey(OurECC) %>% 
  extract2("Sankey") %>% # Extracts the "Sankey" column
  extract2(1)            # Extracts the first row of the "Sankey" column

The new Sankey diagram is:

DoubleRes <- DoubleRes %>% 
  new_Y()
make_sankey(DoubleRes, R = "R_prime", U = "U_prime", V = "V_prime", Y = "Y_prime") %>% 
  extract2("Sankey") %>% 
  extract2(1)

Output from the electricity grid is clearly larger now than before. Also, upstream demand for natural gas is now larger than the upstream demand for crude, whereas in the original Sankey diagram, demand for crude was larger than the demand for natural gas.

What if resources change? Function new_R_ps()

new_Y() estimates the upstream effects of a change to final demand. But what if we want to understand the downstream effects of a change in resource availability? The function new_R_ps() supplies the answer. new_R_ps() takes as input the input-output structure of an ECC and the efficiency of every intermediate industry. After discussing the resource matrix and resource vectors, the new_R_ps() function is demonstrated.

Resource matrices and vectors

The rate of resource extraction is given by the \(\mathbf{R}\) matrix or by the \(\mathbf{r}\) vector. The resource matrix (\(\mathbf{R}\)) is Industry\(\times\)Product. Its industries are usually named Resources - <Product>, where <Product> is the name of the Product produced by that industry. (clean_byname() removes 0 rows and columns for clarity.)

OurECC$R[[1]] %>% 
  clean_byname()
#>                      Crude    NG
#> Resources [of Crude] 50000     0
#> Resources [of NG]        0 43000
#> attr(,"rowtype")
#> [1] "Industry"
#> attr(,"coltype")
#> [1] "Product"

The resource vector (\(\mathbf{r}\)) is a Product column vector containing Products that are resources.

rvecs <- OurECC %>% 
  transmute(
    r = clean_byname(R) %>% 
      colsums_byname() %>% 
      transpose_byname()
  )
rvecs$r[[1]]
#>       Industry
#> Crude    50000
#> NG       43000
#> attr(,"rowtype")
#> [1] "Product"
#> attr(,"coltype")
#> [1] "Industry"

Industry efficiencies and a new resource matrix

The baseline \(\mathbf{R}\) matrix is shown above. Let’s say we want to estimate the effect of a 50 % reduction in the production rate of crude oil. So, we cut Resources - Crude in half. To execute this reduction, we’ll use the matsbyname::elementapply_byname() function.

half <- function(x){
  x/2
}
HalfCrude <- OurECC %>% 
  # Obtain the I-O structure of the ECCs
  calc_io_mats(direction = "downstream") %>% 
  mutate(
    R_prime = elementapply_byname(half, a = R, row = "Resources [of Crude]", col = "Crude")
  )
HalfCrude$R_prime[[1]] %>% clean_byname()
#>                      Crude    NG
#> Resources [of Crude] 25000     0
#> Resources [of NG]        0 43000
#> attr(,"rowtype")
#> [1] "Industry"
#> attr(,"coltype")
#> [1] "Product"

Now we use the new_R() function to estimate changes in the ECC. But first, we need to calculate the efficiency of all sectors in the ECC using the calc_eta_i() function.

HalfCrude <- HalfCrude %>% 
  calc_eta_i() %>% 
  new_R_ps()
glimpse(HalfCrude)
#> Rows: 1
#> Columns: 35
#> $ Country      <chr> "GBR"
#> $ Year         <dbl> 2000
#> $ Energy.type  <chr> "E"
#> $ Last.stage   <chr> "Final"
#> $ R            <list> <<matrix[2 x 2]>>
#> $ r_EIOU       <list> <<matrix[12 x 9]>>
#> $ S_units      <list> <<matrix[12 x 1]>>
#> $ U            <list> <<matrix[12 x 9]>>
#> $ U_EIOU       <list> <<matrix[7 x 8]>>
#> $ U_feed       <list> <<matrix[9 x 9]>>
#> $ V            <list> <<matrix[9 x 10]>>
#> $ Y            <list> <<matrix[4 x 2]>>
#> $ y            <list> <<matrix[4 x 1]>>
#> $ q            <list> <<matrix[12 x 1]>>
#> $ f            <list> <<matrix[9 x 1]>>
#> $ g            <list> <<matrix[9 x 1]>>
#> $ h            <list> <<matrix[2 x 1]>>
#> $ r            <list> <<matrix[2 x 1]>>
#> $ W            <list> <<matrix[12 x 9]>>
#> $ Z_s          <list> <<matrix[10 x 9]>>
#> $ C_s          <list> <<matrix[12 x 9]>>
#> $ D_s          <list> <<matrix[9 x 12]>>
#> $ D_feed_s     <list> <<matrix[9 x 12]>>
#> $ O_s          <list> <<matrix[12 x 2]>>
#> $ B            <list> <<matrix[10 x 12]>>
#> $ G_pxp        <list> <<matrix[12 x 12]>>
#> $ G_ixp        <list> <<matrix[9 x 12]>>
#> $ R_prime      <list> <<matrix[2 x 2]>>
#> $ eta_i        <list> <<matrix[9 x 1]>>
#> $ U_prime      <list> <<matrix[12 x 9]>>
#> $ U_feed_prime <list> <<matrix[12 x 9]>>
#> $ U_EIOU_prime <list> <<matrix[12 x 9]>>
#> $ r_EIOU_prime <list> <<matrix[12 x 9]>>
#> $ V_prime      <list> <<matrix[9 x 10]>>
#> $ Y_prime      <list> <<matrix[12 x 2]>>

After re-calculating the HalfCrude ECC (specifically, after calculating U_prime, V_prime, and Y_prime), we can visualize the effect of lower crude oil availability with a modified Sankey diagram.

First, we have the original Sankey diagram.

make_sankey(OurECC) %>% 
  extract2("Sankey") %>% # Extracts the "Sankey" column
  extract2(1) # Extracts the first row of the "Sankey" column

And here is the modified Sankey diagram showing the much smaller Resources - Crude extraction rate.

make_sankey(HalfCrude, R = "R_prime", U = "U_prime", V = "V_prime", Y = "Y_prime") %>% 
  extract2("Sankey") %>% # Extracts the "Sankey" column
  extract2(1) # Extracts the first row of the "Sankey" column

The Sankey diagrams clearly show that reducing the availability of crude oil (Resources - crude) means that less Transport final demand can be satisfied.

Note that both ECCs are in complete energy balance.

OurECC %>% 
  verify_SUT_energy_balance_with_units() %>% 
  select(Country, Year, Energy.type, Last.stage, 
         .SUT_prod_energy_balance, .SUT_ind_energy_balance) %>% 
  glimpse()
#> Rows: 1
#> Columns: 6
#> $ Country                  <chr> "GBR"
#> $ Year                     <dbl> 2000
#> $ Energy.type              <chr> "E"
#> $ Last.stage               <chr> "Final"
#> $ .SUT_prod_energy_balance <lgl> TRUE
#> $ .SUT_ind_energy_balance  <lgl> TRUE
HalfCrude %>% 
  mutate(
    R_plus_V_prime = sum_byname(R_prime, V_prime)
  ) %>% 
  verify_SUT_energy_balance(R = "R_prime", U = "U_prime", V = "V_prime", 
                            Y = "Y_prime") %>% 
  select(Country, Year, Energy.type, Last.stage,
         .SUT_energy_balance) %>% 
  glimpse()
#> Rows: 1
#> Columns: 5
#> $ Country             <chr> "GBR"
#> $ Year                <dbl> 2000
#> $ Energy.type         <chr> "E"
#> $ Last.stage          <chr> "Final"
#> $ .SUT_energy_balance <lgl> TRUE

What if perfectly-substitutable inputs to an intermediate industry change? Function new_k_ps()

new_Y() estimates the upstream effects of a change in final demand. new_R_ps() estimates the downstream effects of a change in resource availability. But what if we want to estimate the effects of a change to the inputs of an intermediate industry? If those inputs are perfectly substitutable, the new_k_ps() function provides an answer.

To demonstrate new_k_ps(), we need an ECC that has at least two reasonably-sized inputs. Unfortunately, OurECC doesn’t have the necessary characteristics, so we create a new ECC here.

ECC below has two resource industries (R1 and R2), one intermediate industry (I), and two final demand sectors (Y1 and Y2). The R1 industry makes product R1p.
The R2 industry makes product R2p. Industry I makes product Ip. Product Ip is consumed by final demand sectors Y1 and Y2.

The use (\(\mathbf{U}\)), make (\(\mathbf{V}\)), final demand (\(\mathbf{Y}\)), and unit summation (\(\mathbf{S}_{units}\)) matrices are given below.

U <- matrix(c(0, 0, 10,
              0, 0, 10,
              0, 0,  0),
            byrow = TRUE, nrow = 3, ncol = 3,
            dimnames = list(c("R1p", "R2p", "Ip"), c("R1", "R2", "I"))) %>% 
  setrowtype("Products") %>% setcoltype("Industries")

# There is no EIOU, so U_feed is the same as U
U_feed <- U

R_plus_V <- matrix(c(10,  0, 0,
               0, 10, 0, 
               0,  0, 4), 
            byrow = TRUE, nrow = 3, ncol = 3, 
            dimnames = list(c("R1", "R2", "I"), c("R1p", "R2p", "Ip"))) %>% 
  setrowtype("Industries") %>% setcoltype("Products")

Y <- matrix(c(0, 0,
              0, 0, 
              2, 2),
            byrow = TRUE, nrow = 3, ncol = 2,
            dimnames = list(c("R1p", "R2p", "Ip"), c("Y1", "Y2"))) %>% 
  setrowtype("Products") %>% setcoltype("Industries")

RV <- separate_RV(U = U, R_plus_V = R_plus_V)
R <- RV$R
V <- RV$V

S_units <- matrix(c(1, 
                    1, 
                    1), 
                  byrow = TRUE, nrow = 3, ncol = 1,
                  dimnames = list(c("R1p", "R2p", "Ip"), c("quad"))) %>% 
  setrowtype("Products") %>% setcoltype("Units")

The Sankey diagram for this simple ECC is given below.

make_sankey(R = R, U = U, V = V, Y = Y) %>% 
  extract2("Sankey")

We can change the proportion of inputs to industry I using new_k_ps(). To do so, we must first calculate the input-output structure of the ECC using the calc_io_mats() function. Then, we call the new_k_ps() function with a new k vector that indicates industry I now uses 75/25 mixture of R1 and R2 instead of a 50/50 split between R1 and R2.

simple_iomats <- calc_io_mats(R = R, U = U, U_feed = U_feed, V = V, Y = Y, S_units = S_units)
k_prime <- matrix(c(0.75,
                    0.25), 
                  byrow = TRUE, nrow = 2, ncol = 1,
                  dimnames = list(c("R1p", "R2p"), c("I"))) %>% 
  setrowtype("Products") %>% setcoltype("Industries")
change_input_proportions <- new_k_ps(c(simple_iomats, 
                                       list(R = R, U = U, V = V, Y = Y, 
                                            S_units = S_units, 
                                            k_prime = k_prime)))
make_sankey(R = change_input_proportions$R_prime, 
            U = change_input_proportions$U_prime, 
            V = change_input_proportions$V_prime, 
            Y = Y) %>% 
  extract2("Sankey")

In response to the different demands from industry I, the rate of resource extraction from R1 would need to grow, and the rate of resource extraction from supply R2 would need to shrink. If there were additional upstream industries, they would also change in response to the new ratio of inputs to industry I.

Conclusion

Recca has three functions that allow an analyst to estimate the effect of changes to an ECC.

  • new_Y() estimates changes upstream of final demand.
  • new_R_ps() estimates changes downstream from resource extraction.
  • new_k_ps() estimates changes upstream of inputs to an intermediate industry.

The first of these functions (new_Y()) was demonstrated in Heun et al. (2018). The second and third functions (new_R_ps() and new_k_ps()) are shown here for the first time.

References

Heun, Matthew Kuperus, Anne Owen, and Paul E. Brockway. 2018. “A Physical Supply-Use Table Framework for Energy Analysis on the Energy Conversion Chain.” Applied Energy 226 (September): 1134–62. https://doi.org/10.1016/j.apenergy.2018.05.109.
Leontief, Wassily W. 1941. The Structure of American Economy, 1919-1929: An Empirical Application of Equilibrium Analysis. Cambridge, Massachusetts: Harvard University Press.