Skip to content

Instantly share code, notes, and snippets.

@WesIngwersen
Last active August 14, 2023 16:58
Show Gist options
  • Save WesIngwersen/3026cf55a30e8f247d8bd7f02f62cbaa to your computer and use it in GitHub Desktop.
Save WesIngwersen/3026cf55a30e8f247d8bd7f02f62cbaa to your computer and use it in GitHub Desktop.
Demonstrating the useeior adjustment procedure for satellite totals to create coefficients in the form of physical value per IO table dollar year

For this example I am running the model "USEEIOv2.1.19-GHG". I'd like to see what happens to the coefficient for Carbon dioxide from the Electric power industry. For convenience I worked right in the pulled useeior code (master branch) and I put the model spec file for that model into the useeior/inst/extdata/modelspecs folder.
Instead of loading the built useeior library, I use devtools to load_all() the functions and data in the package

For building the model, I just first want to run the initial steps to get what is needed for this example.

modelname <- "USEEIOv2.1.19-GHG"
model <- initializeModel(modelname)
model <- loadIOData(model)
model <- loadandbuildSatelliteTables(model)


Note that the last three lines are what's inside the wrapper buildModel function.

That results in an incomplete model object but it has the satellite table data and output data needed.

Now let's looking inside the useeior code. The buildModel.R script has the high level functions controlling this model build.

Within buildModel.R, the satellite table coefficient building happens during the beginning of constructEEIOMatrices(). A totals by sector df (TbS) is added to the model list as model$TbS which is needed because called the function to create the coefficient-by-sector df, CbS

lns 21-27 of buildModel.R

constructEEIOMatrices <- function(model) {
  # Combine data into a single totals by sector df
  model$TbS <- do.call(rbind,model$SatelliteTables$totals_by_sector)
  # Set common year for flow when more than one year exists
  model$TbS <- setCommonYearforFlow(model$TbS)
  # Generate coefficients 
  model$CbS <- generateCbSfromTbSandModel(model)

I'm running the first two lined for my example model so that I have the TbS to work with Let's see what the total CO2 is for Electric power by subsetting the dataframe(df) and save that value as CO2_total

#Get value just for CO2 for electricity power sector
df <- subset(model$TbS, (Flowable=="Carbon dioxide" & Sector=="221100"), select=c("Flowable","FlowAmount","Unit","SectorName","Year"))
df
#      Flowable   FlowAmount Unit                                                SectorName Year
#Carbon dioxide 1.332348e+12   kg Electric power generation, transmission, and distribution 2019

CO2_total <- df$FlowAmount

Processing with the modeling building code, take a look at what happens that is relevant inside generateCbSfromTbSandModel()

lns 172-177, buildModel.R

      for (year in data_years){
        cbs_r_y <- generateFlowtoDollarCoefficient(tbs_r[tbs_r$Year==year, ], year,
                                                   model$specs$IOYear, r, IsRoUS = IsRoUS,
                                                   model, output_type = "Industry")
        cbs_r <- rbind(cbs_r,cbs_r_y)
      }

For every year present in the totals-by-setor df, the records are subset and sent to this function. Note that the IOYear is sent as well. Looking at what this function takes as parameter. The year of the total-by-sector value, which is the same as the data year, is set as the output year, and the IO table year is sent as the reference year.

lns 68-70, SatelliteFunctions.R

generateFlowtoDollarCoefficient <- function (sattable, outputyear, referenceyear, location_acronym, IsRoUS = FALSE, model, output_type = "Industry") {
  # Generate adjusted industry output
  Output_adj <- adjustOutputbyCPI(outputyear, referenceyear, location_acronym, IsRoUS, model, output_type)

The 'adjustOutputbyCPI' receives the output year and reference year. Let's take a look at it

lns 11-15, IOFunctions.R

adjustOutputbyCPI <- function (outputyear, referenceyear, location_acronym, IsRoUS, model, output_type) {
  # Load Industry Gross Output
  selected_rows <- grepl(location_acronym, rownames(model$MultiYearIndustryOutput))
  Output <- cbind.data.frame(rownames(model$MultiYearIndustryOutput[selected_rows, ]),
                             model$MultiYearIndustryOutput[selected_rows, as.character(outputyear)])

Initially this function is just getting the output of the output year for the location of interest. This returns a df of output by industry for the output year.

For my example, I will set the values I need to set so I can get this Output df.

outputyear <- 2019

> model$specs$IOYear
#[1] 2012

referenceyear <- model$specs$IOYear

location_acronym <- "US"
IsRoUS <- FALSE

output_type <- "Industry"

The I will get the output for electricity for 2019. That is in 2019 USD (current prices).

# What is 2019 output
x_elec <- subset(Output,SectorCode=="221100/US",select=Output)
x_elec <- as.numeric(x_elec)
x_elec
#[1] 4.39108e+11

With that I can calculate a coefficient of CO2_total over that output that represents 2019 CO2 emissions intensity per 2019 USD output from the electric power sector.

CO2_elec_kg_per_2019USD <- CO2_total/x_elec
CO2_elec_kg_per_2019USD
#[1] 3.034216

useeior does not calculate or store that coefficient directly. Instead it wants to adjust that 2019 output from 2019 USD to to 2012 USD and store that.

lns 18-21, IOFunctions.R

  AdjustedOutput <- merge(Output, model[[paste0("MultiYear", output_type, "CPI")]][, as.character(c(referenceyear, outputyear))],
                          by.x = "SectorCode", by.y = 0)
  AdjustedOutput$DollarRatio <- AdjustedOutput[, as.character(referenceyear)]/AdjustedOutput[, as.character(outputyear)]
  AdjustedOutput[, paste(outputyear, "IndustryOutput", sep = "")] <- AdjustedOutput$Output * AdjustedOutput$DollarRatio
  # Assign rownames and keep wanted column

To do this it is getting the CPI (gross output chain-price indices) for both the reference year (model IO data year) and the output year. Then the DollarRatio, which is denoted as &rho or "rho" in eq. 6 of the USEEIO paper, is created. In this next line, this ratio of reference year to output year is then multiplied, as in eq 5 to , by the original output year output. This effectively results in the output year output being converted into reference year dollars.

In our example here is what we get

df <- subset(AdjustedOutput,SectorCode=="221100/US")
df
#   SectorCode      Output 2012     2019 DollarRatio
#22  221100/US 4.39108e+11  100 111.9201   0.8934946
rho <- df$DollarRatio

The rho of 2012:2019 USD ~0.89. So we just multiply this to convert a 2019 USD value to 2012 USD as done in adjusted output (the 2019 USD unit cancels out).

x_elec_adj <- x_elec * rho
x_elec_adj
#[1] 392340608301

So x_elec_adj is our 2019 electricity output converted into 2012 USD.

Returning now to generateFlowtoDollarCoefficient() where the coefficient is yet to be created:

lns 73,80 SatelliteFunctions.R

  Sattable_USEEIO_wOutput <- merge(sattable, Output_adj, by.x = "Sector", by.y = 0, all.x = TRUE)
  ...
  Sattable_USEEIO_wOutput$FlowAmount <- Sattable_USEEIO_wOutput$FlowAmount/Sattable_USEEIO_wOutput[, outputcolname]

The adjusted output df is merged back with the satellite table. Then, the original flow total by sector from that output year is divided by the adjusted output value. This is done by row arithimatically but is equivalent to the matrix algebra formular in Eq 4 in the paper.

In our example, we can do this for the single values we;ve saved to to calculate the electric power CO2 coefficient in CO2/2012 USD

CO2_elec_kg_per_2012USD <-  CO2_total/x_elec_adj
CO2_elec_kg_per_2012USD
[1] 3.395897

And we can check that this value is the same in running the useeior code in buildModel for the CbS

#check this against whats in the model CbS
model$CbS <- generateCbSfromTbSandModel(model)
df <- subset(model$CbS,(Flowable=="Carbon dioxide" & Sector=="221100"), select=c("Flowable","FlowAmount","Unit","SectorName"))
df
#Flowable FlowAmount Unit                                                SectorName
#71 Carbon dioxide   3.395897   kg Electric power generation, transmission, and distribution

It is the same.

The buildModel's constructEEIOMatrices() proceeds to create the B matrix from that CbS.

Those values now are using the same denominator in USD 2012 to the direct and associated total requirements matrices, with values in USD 2012/USD 2012.

@MoLi7
Copy link

MoLi7 commented Aug 14, 2023

@WesIngwersen thank you so much for laying out the detailed steps, and you are correct - the final coefficients in USEEIO models are in 2012 USD. This step in adjustOutputbyCPI is critical for understanding what adjustment has been made to output, and I overlooked it when talking to Yi in the first place. Using your 2019 model example, the Output here is output in 2019 nominal value. By applying the CPI adjustment, it is converted to 2012 nominal value and is carried over in subsequent model-building steps.

AdjustedOutput <- merge(Output, model[[paste0("MultiYear", output_type, "CPI")]][, as.character(c(referenceyear, outputyear))],
by.x = "SectorCode", by.y = 0)
AdjustedOutput$DollarRatio <- AdjustedOutput[, as.character(referenceyear)]/AdjustedOutput[, as.character(outputyear)]
AdjustedOutput[, paste(outputyear, "IndustryOutput", sep = "")] <- AdjustedOutput$Output * AdjustedOutput$DollarRatio

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment