Week 3: Changing the Assumptions
Scenario analysis — what happens when the numbers shift?
Introduction
In the content session, you explored sources of uncertainty and audited the assumptions behind biomass carbon accounting. The “official” answer — that biomass emits zero CO₂ — is a policy choice, not a physical measurement. What happens when you change the assumptions?
Today’s goals:
- Estimate the CO₂ cost of shipping wood pellets across the Atlantic
- Test how sensitive the biomass emissions number is to what you include
- Explore carbon payback periods — when (if ever) does biomass break even?
- Compare cumulative emissions under different scenarios
Exercise 1: The CO₂ cost of transport
The UK’s wood pellets travel thousands of kilometres by ship — mostly from the southeastern United States. How much CO₂ does that shipping produce?
For each country of origin in 2024, calculate the transport emissions:
\[\text{Transport CO}_2 = \text{import (tonnes)} \times \text{distance (km)} \times 0.005 \text{ kg CO}_2\text{/tonne-km}\]
Then sum across all origins to get the total transport CO₂ in millions of tonnes (Mt). The shipping emission factor shipping_co2_per_tkm (0.005 kg CO₂ per tonne-km) is already loaded.
import_kt is in kilotonnes, so multiply by 1000 to get tonnes. The emission factor is shipping_co2_per_tkm (0.005 kg CO₂ per tonne-km). To convert kg to Mt, divide by 1,000,000,000 (1e9).
imports_2024$transport_co2_kg <-
imports_2024$import_kt * 1000 *
imports_2024$transport_km *
shipping_co2_per_tkm
transport_total_mt <- sum(______) / 1e9imports_2024 <- imports[imports$year == 2024, ]
imports_2024$transport_co2_kg <-
imports_2024$import_kt * 1000 *
imports_2024$transport_km *
shipping_co2_per_tkm
transport_total_mt <- sum(imports_2024$transport_co2_kg) / 1e9
transport_total_mtAbout 0.25 Mt CO₂ — a quarter of a million tonnes. Is that a big number? If biomass at 40 TWh replaced coal (910 kg CO₂/MWh), it would avoid about 37 Mt CO₂. So transport adds ~0.25 Mt on top of what we’re told is zero — that’s small relative to the coal it replaces, but it’s not zero. And transport is just the beginning of what’s missing from the official figure.
Exercise 2: The supply chain matters
Transport is only part of the supply chain. What about harvesting, chipping, drying, and pelletising the wood? The factors data frame has emission estimates for biomass under different accounting rules.
Calculate the total annual CO₂ emissions (in Mt) from UK biomass electricity in 2024, under both the “official” scenario (zero) and the “with_supply_chain” scenario (390 kg CO₂/MWh). How big is the gap?
1 TWh = 1,000,000 MWh = 1e6 MWh. The “with_supply_chain” scenario for biomass has an emission factor of 390 kg CO₂/MWh.
bio_mwh <- elec$bioenergy_twh[elec$year == 2024] * 1e6
sc_factor <- factors$co2_kg_per_mwh[
factors$fuel == "biomass" &
factors$scenario == "with_supply_chain"
]
sc_co2_mt <- bio_mwh * sc_factor / ______bio_mwh <- elec$bioenergy_twh[elec$year == 2024] * 1e6
sc_factor <- factors$co2_kg_per_mwh[
factors$fuel == "biomass" &
factors$scenario == "with_supply_chain"
]
sc_co2_mt <- bio_mwh * sc_factor / 1e9
sc_co2_mtAbout 15.7 Mt CO₂ per year under the supply chain scenario — counted as zero under official rules. For context, the UK’s total territorial emissions are about 340 Mt. So this accounting gap is roughly 5% of UK emissions. That’s a policy-relevant difference.
Quick check
Look at the biomass emission factors in the factors data frame. Which assumption has the largest effect on the answer: including the supply chain, or choosing a different carbon payback period?
Enter 1 if supply chain matters more, or 2 if payback period matters more.
Exercise 3: Carbon payback periods
The “carbon payback” idea: when you burn a tree, it releases CO₂ immediately. A new tree growing in its place reabsorbs that CO₂ — but slowly. The payback period is how long until the forest has recaptured all the carbon.
Plot a comparison of biomass emission factors across all six scenarios. This shows the range of answers depending on your assumptions.
Filter with factors$fuel == "biomass". The y-axis should be co2_kg_per_mwh. The factor() call reorders the bars — just fill in the blanks.
bio_factors <- factors[factors$fuel == "biomass", ]
# ...
ggplot(bio_factors, aes(x = scenario, y = co2_kg_per_mwh)) +
geom_col() + ...bio_factors <- factors[factors$fuel == "biomass", ]
bio_factors$scenario <- factor(
bio_factors$scenario,
levels = bio_factors$scenario[order(bio_factors$co2_kg_per_mwh)]
)
ggplot(bio_factors, aes(x = scenario, y = co2_kg_per_mwh)) +
geom_col() +
labs(x = "Accounting scenario",
y = "CO₂ (kg per MWh)",
title = "Biomass CO₂: the answer depends on the question") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))The range is enormous — from 0 to 390 kg CO₂/MWh. The “official” answer is at one extreme. With a 100-year payback, biomass is nearly carbon-neutral (15 kg/MWh). With a 20-year payback, it’s 120 kg/MWh. If you count the full supply chain, it’s 390 — comparable to gas. Which number you choose depends on what question you’re answering and what timescale you care about.
Exercise 4: Cumulative emissions — biomass vs coal
One way to think about payback periods: plot cumulative CO₂ over time for biomass versus coal, assuming a constant generation rate. If biomass replaces coal, when does the carbon “debt” get repaid?
Build a data frame with years 1–50, then calculate cumulative emissions for coal (910 kg/MWh) and biomass at different payback assumptions. Use 2024’s generation (40.3 TWh) as the constant rate.
The emission factors are: coal = 910, biomass supply chain = 390, biomass 20-year payback = 120 (all in kg CO₂/MWh). cumsum() gives the running total. Each year adds annual_mwh × factor / 1e9 Mt.
bio_sc_cumul <- cumsum(rep(annual_mwh * 390 / 1e9, 50))
bio_20_cumul <- cumsum(rep(annual_mwh * 120 / 1e9, 50))annual_mwh <- 40.3 * 1e6
years <- 1:50
coal_cumul <- cumsum(rep(annual_mwh * 910 / 1e9, 50))
bio_sc_cumul <- cumsum(rep(annual_mwh * 390 / 1e9, 50))
bio_20_cumul <- cumsum(rep(annual_mwh * 120 / 1e9, 50))
scenarios <- data.frame(
year = rep(years, 3),
cumul_mt = c(coal_cumul, bio_sc_cumul, bio_20_cumul),
scenario = rep(c("Coal (910)", "Biomass supply chain (390)",
"Biomass 20yr payback (120)"),
each = 50)
)
ggplot(scenarios, aes(x = year, y = cumul_mt, colour = scenario,
linetype = scenario)) +
geom_line() +
labs(x = "Years",
y = "Cumulative CO₂ (Mt)",
colour = "Scenario",
title = "Cumulative emissions: coal vs biomass scenarios")Biomass always emits less cumulatively than coal — but it’s not zero. Under the supply chain scenario, 50 years of biomass generation emits about 786 Mt CO₂. Under the 20-year payback, it’s about 242 Mt. Coal would emit about 1,837 Mt. Biomass is better than coal, but “better than coal” and “carbon-neutral” are very different claims. Note: this simplified model assumes constant emission rates — real payback changes over time as the forest regrows.
Extension: Best case vs worst case
This exercise is optional — for students who finish early.
Combine the most favourable assumptions for biomass (100-year payback: 15 kg/MWh) and the least favourable (full supply chain: 390 kg/MWh) into a single plot. Add coal and gas for comparison. How wide is the uncertainty range?
Try building this as a bar chart with error-bar-style ranges, or as multiple lines on a cumulative emissions plot.
geom_errorbar(aes(ymin = ..., ymax = ...)) draws range bars. You’re not limited to this approach — a grouped bar chart or multiple cumulative lines would also work well.
range_df <- data.frame(
fuel = c("Biomass", "Coal", "Gas"),
best = c(15, 910, 360),
worst = c(390, 990, 410)
)
range_df$mid <- (range_df$best + range_df$worst) / 2
ggplot(range_df, aes(x = fuel)) +
geom_errorbar(aes(ymin = best, ymax = worst), width = 0.3) +
geom_point(aes(y = mid), size = 3) +
labs(x = "Fuel",
y = "CO₂ (kg per MWh)",
title = "Emission factor ranges by fuel",
caption = "Points show midpoint; bars show range of estimates")The range for biomass (15–390 kg/MWh) is vastly wider than for coal (910–990) or gas (360–410). For coal and gas, the uncertainty is about supply chain details. For biomass, the uncertainty spans the fundamental question of whether it’s nearly carbon-free or comparable to gas. That’s not a small disagreement — it’s a factor of 26.
This is the core insight of the mini-project: the answer depends on the assumptions, and the assumptions are a choice.
Save your work
Copy your scenario analysis code into week3.R in your GitHub repo. Commit and push via GitHub Desktop. Write a commit message that explains what you discovered about the assumptions — not just “week 3 exercises”.