energy_totals: combined energy totals for all years
This commit is contained in:
parent
eee6651d12
commit
ba8b3f9ce7
@ -243,6 +243,7 @@ rule build_energy_totals:
|
|||||||
district_heat_share='data/district_heat_share.csv',
|
district_heat_share='data/district_heat_share.csv',
|
||||||
eurostat=directory("data/eurostat-energy_balances-june_2021_edition"),
|
eurostat=directory("data/eurostat-energy_balances-june_2021_edition"),
|
||||||
output:
|
output:
|
||||||
|
energy_name_full='resources/energy_totals_full.csv',
|
||||||
energy_name='resources/energy_totals.csv',
|
energy_name='resources/energy_totals.csv',
|
||||||
co2_name='resources/co2_totals.csv',
|
co2_name='resources/co2_totals.csv',
|
||||||
transport_name='resources/transport_data.csv'
|
transport_name='resources/transport_data.csv'
|
||||||
|
@ -125,21 +125,25 @@ def build_eurostat(countries, year=None):
|
|||||||
# convert ktoe/a to TWh/a
|
# convert ktoe/a to TWh/a
|
||||||
df *= 11.63 / 1e3
|
df *= 11.63 / 1e3
|
||||||
|
|
||||||
|
df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1)
|
||||||
|
|
||||||
if year:
|
if year:
|
||||||
df = df.xs(str(year), level='year')
|
df = df.xs(year, level='year')
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
def build_swiss(year=None):
|
def build_swiss(year=None):
|
||||||
"""Return a pd.Series of Swiss energy data in TWh/a"""
|
"""Return a pd.DataFrame of Swiss energy data in TWh/a"""
|
||||||
|
|
||||||
fn = snakemake.input.swiss
|
fn = snakemake.input.swiss
|
||||||
|
|
||||||
df = pd.read_csv(fn, index_col=[0,1]).loc["CH"]
|
df = pd.read_csv(fn, index_col=[0,1]).stack().unstack('item')
|
||||||
|
df.index.names = ["country", "year"]
|
||||||
|
df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1)
|
||||||
|
|
||||||
if year:
|
if year:
|
||||||
df = df[str(year)]
|
df = df.xs(year, level='year')
|
||||||
|
|
||||||
# convert PJ/a to TWh/a
|
# convert PJ/a to TWh/a
|
||||||
df /= 3.6
|
df /= 3.6
|
||||||
@ -373,6 +377,8 @@ def build_idees(countries, year=None):
|
|||||||
if year:
|
if year:
|
||||||
df = df.xs(int(year), level='year')
|
df = df.xs(int(year), level='year')
|
||||||
|
|
||||||
|
df.columns.name = 'item'
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
@ -391,15 +397,21 @@ def build_energy_totals(countries, eurostat, swiss, idees):
|
|||||||
)
|
)
|
||||||
|
|
||||||
to_drop = ["passenger cars", "passenger car efficiency"]
|
to_drop = ["passenger cars", "passenger car efficiency"]
|
||||||
df = idees.reindex(countries).drop(to_drop, axis=1)
|
|
||||||
|
new_index = pd.MultiIndex.from_product(
|
||||||
|
[countries, eurostat.index.levels[1]],
|
||||||
|
names=["country", "year"]
|
||||||
|
)
|
||||||
|
|
||||||
|
df = idees.reindex(new_index).drop(to_drop, axis=1)
|
||||||
|
|
||||||
eurostat_countries = eurostat.index.levels[0]
|
eurostat_countries = eurostat.index.levels[0]
|
||||||
in_eurostat = df.index.intersection(eurostat_countries)
|
in_eurostat = df.index.levels[0].intersection(eurostat_countries)
|
||||||
|
|
||||||
# add international navigation
|
# add international navigation
|
||||||
|
|
||||||
slicer = idx[in_eurostat, :, "International maritime bunkers", :]
|
slicer = idx[in_eurostat, :, :, "International maritime bunkers", :]
|
||||||
fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum()
|
fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum()
|
||||||
df.loc[in_eurostat, "total international navigation"] = fill_values
|
df.loc[in_eurostat, "total international navigation"] = fill_values
|
||||||
|
|
||||||
# add swiss energy data
|
# add swiss energy data
|
||||||
@ -409,17 +421,20 @@ def build_energy_totals(countries, eurostat, swiss, idees):
|
|||||||
# get values for missing countries based on Eurostat EnergyBalances
|
# get values for missing countries based on Eurostat EnergyBalances
|
||||||
# divide cooking/space/water according to averages in EU28
|
# divide cooking/space/water according to averages in EU28
|
||||||
|
|
||||||
missing = df.index[df["total residential"].isna()]
|
to_fill = df.index[df["total residential"].isna() & df.index.get_level_values('country').isin(eurostat_countries)]
|
||||||
to_fill = missing.intersection(eurostat_countries)
|
|
||||||
uses = ["space", "cooking", "water"]
|
uses = ["space", "cooking", "water"]
|
||||||
|
|
||||||
|
c = to_fill.get_level_values('country')
|
||||||
|
y = to_fill.get_level_values('year')
|
||||||
|
|
||||||
for sector in ["residential", "services", "road", "rail"]:
|
for sector in ["residential", "services", "road", "rail"]:
|
||||||
|
|
||||||
# fuel use
|
# fuel use
|
||||||
|
|
||||||
for fuel in ["electricity", "total"]:
|
for fuel in ["electricity", "total"]:
|
||||||
slicer = idx[to_fill, :, :, eurostat_sectors[sector]]
|
|
||||||
fill_values = eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=0).sum()
|
slicer = idx[c, y, :, :, eurostat_sectors[sector]]
|
||||||
|
fill_values = eurostat.loc[slicer, eurostat_fuels[fuel]].groupby(level=[0,1]).sum()
|
||||||
df.loc[to_fill, f"{fuel} {sector}"] = fill_values
|
df.loc[to_fill, f"{fuel} {sector}"] = fill_values
|
||||||
|
|
||||||
for sector in ["residential", "services"]:
|
for sector in ["residential", "services"]:
|
||||||
@ -462,28 +477,28 @@ def build_energy_totals(countries, eurostat, swiss, idees):
|
|||||||
nonelectric_use = no_norway[f"total {sector} {use}"] - no_norway[f"electricity {sector} {use}"]
|
nonelectric_use = no_norway[f"total {sector} {use}"] - no_norway[f"electricity {sector} {use}"]
|
||||||
nonelectric = no_norway[f"total {sector}"] - no_norway[f"electricity {sector}"]
|
nonelectric = no_norway[f"total {sector}"] - no_norway[f"electricity {sector}"]
|
||||||
fraction = nonelectric_use.div(nonelectric).mean()
|
fraction = nonelectric_use.div(nonelectric).mean()
|
||||||
df.loc["NO", f"total {sector} {use}"] = total_heating * fraction
|
df.loc["NO", f"total {sector} {use}"] = (total_heating * fraction).values
|
||||||
df.loc["NO", f"electricity {sector} {use}"] = total_heating * fraction * elec_fraction
|
df.loc["NO", f"electricity {sector} {use}"] = (total_heating * fraction * elec_fraction).values
|
||||||
|
|
||||||
# Missing aviation
|
# Missing aviation
|
||||||
|
|
||||||
slicer = idx[to_fill, :, :, "Domestic aviation"]
|
slicer = idx[c, y, :, :, "Domestic aviation"]
|
||||||
fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum()
|
fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum()
|
||||||
df.loc[to_fill, "total domestic aviation"] = fill_values
|
df.loc[to_fill, "total domestic aviation"] = fill_values
|
||||||
|
|
||||||
slicer = idx[to_fill, :, "International aviation", :]
|
slicer = idx[c, y, :, "International aviation", :]
|
||||||
fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum()
|
fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum()
|
||||||
df.loc[to_fill, "total international aviation"] = fill_values
|
df.loc[to_fill, "total international aviation"] = fill_values
|
||||||
|
|
||||||
# missing domestic navigation
|
# missing domestic navigation
|
||||||
|
|
||||||
slicer = idx[to_fill, :, :, "Domestic navigation"]
|
slicer = idx[c, y, :, :, "Domestic navigation"]
|
||||||
fill_values = eurostat.loc[slicer, "Total"].groupby(level=0).sum()
|
fill_values = eurostat.loc[slicer, "Total"].groupby(level=[0,1]).sum()
|
||||||
df.loc[to_fill, "total domestic navigation"] = fill_values
|
df.loc[to_fill, "total domestic navigation"] = fill_values
|
||||||
|
|
||||||
# split road traffic for non-IDEES
|
# split road traffic for non-IDEES
|
||||||
missing = df.index[df["total passenger cars"].isna()]
|
missing = df.index[df["total passenger cars"].isna()]
|
||||||
for fuel in ["total", "electricity"]:
|
for fuel in ["electricity", "total"]:
|
||||||
selection = [
|
selection = [
|
||||||
f"{fuel} passenger cars",
|
f"{fuel} passenger cars",
|
||||||
f"{fuel} other road passenger",
|
f"{fuel} other road passenger",
|
||||||
@ -525,19 +540,20 @@ def build_energy_totals(countries, eurostat, swiss, idees):
|
|||||||
df.loc[missing, f"total aviation {purpose}"] = df.loc[missing, attrs].sum(axis=1)
|
df.loc[missing, f"total aviation {purpose}"] = df.loc[missing, attrs].sum(axis=1)
|
||||||
|
|
||||||
if "BA" in df.index:
|
if "BA" in df.index:
|
||||||
# fill missing data for BA (services and road energy data)
|
# fill missing data for BA proportional to RS
|
||||||
# proportional to RS with ratio of total residential demand
|
ratio = (df.loc["BA"].loc[2014:2020] / df.loc["RS"].loc[2014:2020]).mean()
|
||||||
missing = df.loc["BA"] == 0.0
|
df.loc["BA"] = (ratio * df.loc["RS"]).values
|
||||||
ratio = df.at["BA", "total residential"] / df.at["RS", "total residential"]
|
|
||||||
df.loc['BA', missing] = ratio * df.loc["RS", missing]
|
|
||||||
|
|
||||||
# Missing district heating share
|
# Missing district heating share
|
||||||
dh_share = pd.read_csv(snakemake.input.district_heat_share,
|
dh_share = pd.read_csv(snakemake.input.district_heat_share,
|
||||||
index_col=0, usecols=[0, 1])
|
index_col=0, usecols=[0, 1])
|
||||||
|
|
||||||
|
dh_share = pd.concat({y: dh_share for y in range(1990, 2021)}, names=["year", "country"]).swaplevel()
|
||||||
|
dh_share = dh_share.div(100).reindex(df.index)
|
||||||
|
|
||||||
# make conservative assumption and take minimum from both data sets
|
# make conservative assumption and take minimum from both data sets
|
||||||
df["district heat share"] = (pd.concat([df["district heat share"],
|
item = "district heat share"
|
||||||
dh_share.reindex(index=df.index)/100],
|
df[item] = pd.concat([dh_share, df[item]], axis=1).min(axis=1)
|
||||||
axis=1).min(axis=1))
|
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
@ -673,6 +689,7 @@ if __name__ == "__main__":
|
|||||||
snakemake = mock_snakemake('build_energy_totals')
|
snakemake = mock_snakemake('build_energy_totals')
|
||||||
|
|
||||||
config = snakemake.config["energy"]
|
config = snakemake.config["energy"]
|
||||||
|
data_year = int(config["energy_totals_year"])
|
||||||
|
|
||||||
nuts3 = gpd.read_file(snakemake.input.nuts3_shapes).set_index("index")
|
nuts3 = gpd.read_file(snakemake.input.nuts3_shapes).set_index("index")
|
||||||
population = nuts3["pop"].groupby(nuts3.country).sum()
|
population = nuts3["pop"].groupby(nuts3.country).sum()
|
||||||
@ -680,12 +697,14 @@ if __name__ == "__main__":
|
|||||||
countries = population.index
|
countries = population.index
|
||||||
idees_countries = countries.intersection(eu28)
|
idees_countries = countries.intersection(eu28)
|
||||||
|
|
||||||
data_year = config["energy_totals_year"]
|
eurostat = build_eurostat(countries.difference(['CH']))
|
||||||
eurostat = build_eurostat(countries.difference(['CH']), data_year)
|
swiss = build_swiss()
|
||||||
swiss = build_swiss(data_year)
|
idees = build_idees(idees_countries)
|
||||||
idees = build_idees(idees_countries, data_year)
|
|
||||||
|
|
||||||
energy = build_energy_totals(countries, eurostat, swiss, idees)
|
energy = build_energy_totals(countries, eurostat, swiss, idees)
|
||||||
|
energy.to_csv(snakemake.output.energy_name_full)
|
||||||
|
|
||||||
|
energy = energy.xs(data_year, level='year')
|
||||||
energy.to_csv(snakemake.output.energy_name)
|
energy.to_csv(snakemake.output.energy_name)
|
||||||
|
|
||||||
base_year_emissions = config["base_emissions_year"]
|
base_year_emissions = config["base_emissions_year"]
|
||||||
|
Loading…
Reference in New Issue
Block a user