Carbon Emission Calculation#
import pandas as pd
The purpose of this calculation is to determine the appropriate total emission constraints based on the defined scope of the model. The objective is to establish the relationship between this target and the total emissions from the year 1990.
The countries included in the analysis are:
AT: Austria
BE: Belgium
CH: Switzerland
CZ: Czech Republic
DE: Germany
DK: Denmark
FR: France
IT: Italy
LU: Luxembourg
NL: Netherlands
PL: Poland
SE: Sweden
The sector scope for this analysis includes:
Power Sector
Transport Sector (fossil fuel emissions are excluded)
Heating Sector
Since the emissions of individual countries are being compared for the years 1990 and 2005, we first need to extract the emissions data for those years.
1. Extract the total emissions data for the years 1990 and 2005.#
ctrys = ['AT', 'BE', 'CH', 'CZ', 'DE', 'DK', 'FR', 'IT', 'LU', 'NL', 'PL', 'SE']
# 1990 emissions in MtCO2
co2_totals = pd.read_csv("../data/co2_totals_1990.csv", index_col=0).loc[ctrys]
# 2005 emissions in MtCO2
co2_totals_2005 = pd.read_csv("../data/co2_totals_2005.csv", index_col=0).loc[ctrys]
2. Calculate the linearly interpolated targets for 2035.#
Below are the emission reduction targets for each of these countries:
Country |
2030 |
2035 |
2040 |
2045 |
2050 |
Source |
---|---|---|---|---|---|---|
DE |
65% below 1990 excl. LULUCF |
- |
85% below 1990 excl. LULUCF |
100% |
- |
|
AT |
48% below 2005 excl. LULUCF |
- |
100% |
- |
- |
|
BE |
55% below 1990 excl. LULUCF |
- |
- |
- |
100% |
|
CH |
50% below 1990 excl. LULUCF |
- |
- |
- |
100% |
|
CZ |
26% below 2005 excl. LULUCF |
- |
- |
- |
100% |
|
DK |
70% below 1990 incl. LULUCF and 50% below 2005 excl. LULUCF |
- |
- |
100% |
110% |
|
FR |
47.5% below 2005 excl. LULUCF |
- |
- |
- |
100% |
|
IT |
43.7% below 2005 excl. LULUCF |
- |
- |
- |
100% |
|
LU |
55% below 2005 excl. LULUCF |
- |
- |
- |
100% |
|
NL |
55% below 1990 |
- |
- |
- |
100% |
|
PL |
17.7% below 2005 excl. LULUCF |
- |
- |
- |
||
SE |
63% below 1990 |
- |
75% below 1990 |
100% |
Since Table 1 do not include the year 2035, we will interpolate the targets linearly to estimate the 2035 values.
Note: Polands 2035 target is deduced based on the EUs Effort Sharing Regulation (ESR) distrubution key in relation to the German interpolated target (source).
# EU Effort Sharing Regulation
esr_targets = {
"AT": 0.48,
"BE": 0.47,
"CZ": 0.26,
"DE": 0.5,
"DK": 0.5,
"FR": 0.475,
"IT": 0.437,
"LU": 0.5,
"NL": 0.48,
"PL": 0.177,
"SE": 0.5,
}
# Emission reduction targets for countries with a base year of 1990
target2035_base1990 = dict(DE = 0.75,
BE = 0.55 + (1-0.55)*(2035-2030)/(2050-2030),
CH = 0.625,
DK = 0.7 + (1-0.7)*(2035-2030)/(2045-2030),
NL = 0.55 + (1-0.55)*(2035-2030)/(2050-2030),
SE = 0.69,
PL = (esr_targets["PL"]/esr_targets["DE"])*0.75
)
# Emission reduction targets for countries with a base year of 2005
target2035_base2005 = dict(AT = 0.74,
CZ = 0.26 + (1-0.26)*(2035-2030)/(2050-2030),
FR = 0.475 + (1-0.475)*(2035-2030)/(2050-2030),
IT = 0.437 + (1-0.437)*(2035-2030)/(2050-2030),
LU = 0.55 + (1-0.55)*(2035-2030)/(2050-2030)
)
target_2035 = pd.DataFrame(index=co2_totals.index)
target_2035["base1990"] = target2035_base1990
target_2035["base2005"] = target2035_base2005
target_2035
base1990 | base2005 | |
---|---|---|
Country_code | ||
AT | NaN | 0.74000 |
BE | 0.6625 | NaN |
CH | 0.6250 | NaN |
CZ | NaN | 0.44500 |
DE | 0.7500 | NaN |
DK | 0.8000 | NaN |
FR | NaN | 0.60625 |
IT | NaN | 0.57775 |
LU | NaN | 0.66250 |
NL | 0.6625 | NaN |
PL | 0.2655 | NaN |
SE | 0.6900 | NaN |
3. Extract the data and exclude LULUCF from the calculation.#
LULUFC: Land Use, Land Use Change and Forestry
LULUCF is excluded for all the countries listed in Table 1.
# Total emissions incl. LULUCF
co2_totals_incl_lulucf = co2_totals.sum(axis=1)
# Total emissions incl. LULUCF 2005
co2_totals_incl_lulucf_2005 = co2_totals_2005.sum(axis=1)
# Total emissions excl. LULUCF
co2_totals_excl_lulucf = co2_totals.drop(["LULUCF"], axis=1).sum(axis=1)
# Total emissions excl. LULUCF
co2_totals_excl_lulucf_2005 = co2_totals_2005.drop(["LULUCF"], axis=1).sum(axis=1)
pd.DataFrame({"1990":co2_totals_incl_lulucf, "2005":co2_totals_incl_lulucf_2005, "1990 excl. LULUFC":co2_totals_excl_lulucf, "2005 excl. LULUFC":co2_totals_excl_lulucf_2005})
1990 | 2005 | 1990 excl. LULUFC | 2005 excl. LULUFC | |
---|---|---|---|---|
Country_code | ||||
AT | 49.968104 | 68.414161 | 62.124701 | 79.192432 |
BE | 117.060288 | 124.024742 | 120.309343 | 125.661688 |
CH | 42.515838 | 43.712103 | 44.534441 | 45.915746 |
CZ | 160.298010 | 119.316791 | 166.068823 | 126.738399 |
DE | 1021.884333 | 851.168952 | 1052.348544 | 866.388549 |
DK | 60.858777 | 57.805099 | 54.685986 | 52.164863 |
FR | 374.572263 | 377.355895 | 400.777042 | 426.412463 |
IT | 432.346810 | 463.962937 | 438.008802 | 500.005676 |
LU | 11.927560 | 11.462305 | 11.847635 | 12.105448 |
NL | 169.786966 | 183.428661 | 163.302301 | 177.897237 |
PL | 343.554029 | 271.748435 | 376.546518 | 323.161267 |
SE | 21.112932 | 19.936933 | 57.348825 | 53.852857 |
4. Calculate the absolute emissions#
This is done by multiplying the remaining emissions (1 - target emissions) by the CO2 emissions for the respective year.
# Calculate aggregated 1990 emissions in MtCO2
co2_1990_aggregated = co2_totals_excl_lulucf.sum()
# Calculate absolute target emissions in 2035 based on shares
target_2035["absolute_emissions"] = ((1-target_2035.base1990) * co2_totals_excl_lulucf).combine_first((1-target_2035.base2005) * co2_totals_excl_lulucf_2005)
target_2035_aggregated = target_2035.absolute_emissions.sum()
display(target_2035)
# Calculate share of 1990 emissions
round(target_2035_aggregated/co2_1990_aggregated,3)
base1990 | base2005 | absolute_emissions | |
---|---|---|---|
Country_code | |||
AT | NaN | 0.74000 | 20.590032 |
BE | 0.6625 | NaN | 40.604403 |
CH | 0.6250 | NaN | 16.700415 |
CZ | NaN | 0.44500 | 70.339812 |
DE | 0.7500 | NaN | 263.087136 |
DK | 0.8000 | NaN | 10.937197 |
FR | NaN | 0.60625 | 167.899907 |
IT | NaN | 0.57775 | 211.127397 |
LU | NaN | 0.66250 | 4.085589 |
NL | 0.6625 | NaN | 55.114527 |
PL | 0.2655 | NaN | 276.573417 |
SE | 0.6900 | NaN | 17.778136 |
0.392
Note: 39.2% (0.392) compared to 1990 emissions is the result when all sectors are included.
Since not all sector is included in the model, we need to divide the remaining emissions further based on the share of remaining emissions in each sector.
5. Extract the emission target by sector and interpolate to the year 2035#
Data is from Europe’s 2040 climate target (Source).
target_sector = pd.read_csv("../data/co2_total_sector.csv", index_col=0)
# calculate linearly interpolated 2035 targets
target_sector['2035 S2'] = (target_sector['2030'] + target_sector['2040 S2'])/2
target_sector_share = target_sector/target_sector.loc['Total Gross GHG Emissions',:]
target_sector
2005 | 2015 | 2030 | 2040 S1 | 2040 S2 | 2040 S3 | 2040 LIFE | 2050 S1 | 2050 S2 | 2050 S3 | 2050 LIFE | 2035 S2 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
MtC02-eq | ||||||||||||
Total Gross GHG Emissions | 4641 | 3914 | 2301 | 1273 | 943 | 748 | 740 | 416 | 413 | 411 | 360.00 | 1622.0 |
Power and district heating | 1300 | 1012 | 339 | 123 | 42 | 23 | 34 | 21 | 22 | 19 | 15.00 | 190.5 |
Other Energy sectors* | 277 | 237 | 133 | 71 | 59 | 53 | 57 | 39 | 39 | 38 | 36.00 | 96.0 |
Industry (Energy) | 469 | 360 | 232 | 126 | 94 | 75 | 86 | 6 | 6 | 9 | 11.00 | 163.0 |
Domestic Transport | 822 | 772 | 583 | 190 | 143 | 120 | 134 | 10 | 8 | 7 | 9.00 | 363.0 |
Residential and Services** | 648 | 514 | 221 | 119 | 92 | 75 | 92 | 20 | 19 | 19 | 29.00 | 156.5 |
Industry (Non-Energy) | 343 | 233 | 157 | 139 | 88 | 14 | 13 | 7 | 7 | 7 | 7.00 | 122.5 |
Other Non-Energv sectors*** | 101 | 130 | 56 | 33 | 26 | 25 | 25 | 23 | 22 | 22 | 22.00 | 41.0 |
Intra-EU aviation | 35 | 38 | 43 | 31 | 29 | 28 | 14 | 14 | 12 | 11 | 10.00 | 36.0 |
Intra-EU navigation | 31 | 27 | 25 | 7 | 6 | 4 | 0 | 0 | 0 | 0 | 0.00 | 15.5 |
50% extra-EU maritime MRV | 50 | 42 | 44 | 14 | 11 | 9 | 0 | 0 | 0 | 0 | 0.00 | 27.5 |
Agriculture**** | 390 | 385 | 361 | 351 | 302 | 271 | 209 | 249 | 249 | 249 | 194.00 | 331.5 |
Waste | 155 | 118 | 87 | 68 | 55 | 55 | 55 | 32 | 32 | 32 | 0.32 | 71.0 |
C02 calibration | 15 | 43 | 24 | 3 | -1 | -1 | -1 | 0 | 0 | 0 | 0.00 | 11.5 |
Non-C02 calibration | 5 | 2 | -3 | -3 | -3 | -3 | -3 | -3 | -3 | -3 | -3.00 | -3.0 |
6. Select the included sector in the model#
In this list, we only model:
Power and district heating
Other Energy sectors*
Residential and Services**
Note:
Other Energy sectors includes emissions from the energy branch as well as other non-CO2 emissions from the energy sector.
The Residential and Services sector may include fossil fuel combustion from the agriculture, fishery, and forestry sectors.
include_sector = ['Power and district heating','Residential and Services**','Other Energy sectors*']
target_sector_share_2035 = target_sector_share.loc[include_sector,'2035 S2'].sum()
target_sector_share_2035
0.27311960542540076
Note: 27.3% (0.273) of the emissions come from the included sector, relative to the total emissions from all sectors.
7. Calculate the absolute emission of the included sector emission#
target_2035['included_sector_emissions'] = target_2035['absolute_emissions'] * target_sector_share_2035
display(target_2035)
# Calculate share of 1990 emissions
round(target_2035['included_sector_emissions'].sum()/co2_1990_aggregated,3)
base1990 | base2005 | absolute_emissions | included_sector_emissions | |
---|---|---|---|---|
Country_code | ||||
AT | NaN | 0.74000 | 20.590032 | 5.623541 |
BE | 0.6625 | NaN | 40.604403 | 11.089859 |
CH | 0.6250 | NaN | 16.700415 | 4.561211 |
CZ | NaN | 0.44500 | 70.339812 | 19.211182 |
DE | 0.7500 | NaN | 263.087136 | 71.854255 |
DK | 0.8000 | NaN | 10.937197 | 2.987163 |
FR | NaN | 0.60625 | 167.899907 | 45.856756 |
IT | NaN | 0.57775 | 211.127397 | 57.663031 |
LU | NaN | 0.66250 | 4.085589 | 1.115854 |
NL | 0.6625 | NaN | 55.114527 | 15.052858 |
PL | 0.2655 | NaN | 276.573417 | 75.537623 |
SE | 0.6900 | NaN | 17.778136 | 4.855557 |
0.107
10.7% (0.107) compared to 1990 emissions is the answer for the co2_budget
for the year 2035