CO2_emission / app.py
Tinsae's picture
covid and policy
bbfa741
import streamlit as st
import pandas as pd
import plotly.express as px
#import bar_chart_race as bcr
from raceplotly.plots import barplot
# Configuration and Constants
COUNTRY_MAPPING = {
"Italy, San Marino and the Holy See": "Italy",
"France and Monaco": "France",
"Belgium and Luxembourg": "Belgium",
"China (mainland)": "China",
"United States of America": "United States",
"United Kingdom of Great Britain and Northern Ireland": "United Kingdom",
"Spain and Andorra": "Spain"
}
DEFAULT_COUNTRIES = ["Italy", "France", "Germany"]
YEAR_RANGE = (2000, 2020)
# Data Loading and Processing Functions
@st.cache_data
def load_data(sheet_name, year_range = (2000, 2020), sector=None):
df = pd.read_excel("dati/fossilco2emission.xlsx", sheet_name=sheet_name)
df_mapped = df.copy()
df_mapped['Country'] = df_mapped['Country'].replace(COUNTRY_MAPPING)
year_cols = list(range(year_range[0], year_range[1] + 1))
if sector:
selected_cols = ['Country', 'Sector'] + year_cols
else:
selected_cols = ['Country'] + year_cols
return df_mapped[selected_cols].copy()
def process_data_for_line_plot(df, selected_countries, year_range):
mask = df['Country'].isin(selected_countries)
filtered_df = df[mask]
df_melted = filtered_df.melt(
id_vars=['Country'],
value_vars=range(year_range[0], year_range[1] + 1),
var_name='Year',
value_name='Emissions'
)
df_melted['Year'] = pd.to_numeric(df_melted['Year'])
return df_melted
# Visualization Functions
def create_line_plot(data):
fig = px.line(
data,
x='Year',
y='Emissions',
color='Country',
title='CO2 Emissions Over Time',
labels={'Emissions': 'CO2 Emissions per Capita (Mton)'},
hover_data={'Year': True, 'Emissions': ':.2f'}
)
fig.update_layout(height=600, hovermode='x unified')
return fig
def create_animated_choropleth(data, start_year, end_year):
df_map = data.melt(
id_vars=['Country'],
value_vars=range(start_year, end_year + 1),
var_name='Year',
value_name='Emissions'
)
fig_map = px.choropleth(
df_map,
locations='Country',
locationmode='country names',
color='Emissions',
animation_frame='Year',
title='CO2 Emissions per Capita Over Time',
color_continuous_scale='Reds',
range_color=[0, df_map['Emissions'].quantile(0.95)],
labels={'Emissions': 'CO2 Emissions per Capita (Mton)'}
)
fig_map.update_layout(
height=600,
margin=dict(l=0, r=0, t=30, b=0),
updatemenus=[{
'type': 'buttons',
'showactive': False,
'buttons': [
dict(label='Play',
method='animate',
args=[None, {'frame': {'duration': 500, 'redraw': True},
'fromcurrent': True}]),
dict(label='Pause',
method='animate',
args=[[None], {'frame': {'duration': 0, 'redraw': False},
'mode': 'immediate',
'transition': {'duration': 0}}])
]
}]
)
return fig_map
def create_race_plot(df, year_range):
# Prepare data for race plot
# Convert year columns to rows for raceplotly format
df_race = df.melt(
id_vars=['Country'],
value_vars=range(year_range[0], year_range[1] + 1),
var_name='Year',
value_name='Emissions'
)
# Create the race plot
race_plot = barplot(
df_race,
item_column='Country',
value_column='Emissions',
time_column='Year',
top_entries=10,
)
# Plot with custom settings
fig = race_plot.plot(
title='Top 10 Countries by CO2 Emissions',
orientation='horizontal',
item_label='Country',
value_label='CO2 Emissions (Mton)',
time_label='Year: ',
frame_duration=800
)
# fig.update_layout(
# height=700, # Make plot taller
# font=dict(size=12), # Increase base font size
# title_font_size=20, # Larger title
# xaxis_title_font_size=16, # Larger axis titles
# yaxis_title_font_size=16,
# yaxis_tickfont_size=14, # Larger tick labels
# xaxis_tickfont_size=14
# )
return fig
def create_covid_impact_plot(df1, df2):
# Create tabs for different COVID analyses
tab1, tab2 = st.tabs(["Global Impact", "Sectoral Impact"])
print(df2.head())
with tab1:
# Global emissions around COVID
years_covid = range(2017, 2023)
global_emissions = df1[df1['Country'] == 'GLOBAL TOTAL']
emissions_covid = global_emissions[list(years_covid)].values[0]
fig_global = px.line(
x=years_covid,
y=emissions_covid,
title='Global CO2 Emissions Around COVID-19',
labels={'x': 'Year', 'y': 'CO2 Emissions (Mt CO2)'}
)
fig_global.add_vline(x=2020, line_dash="dash", line_color="red",
annotation_text="COVID-19")
st.plotly_chart(fig_global, use_container_width=True)
# Calculate and display percentage changes
col1, col2 = st.columns(2)
with col1:
change_2020 = ((emissions_covid[3] - emissions_covid[2])/emissions_covid[2]*100)
st.metric("2020 Emissions Change", f"{change_2020:.1f}%")
with col2:
change_2021 = ((emissions_covid[4] - emissions_covid[3])/emissions_covid[3]*100)
st.metric("2021 Recovery", f"{change_2021:.1f}%")
with tab2:
# Sectoral analysis
sectors = ['Power Industry', 'Industrial Combustion', 'Transport', 'Processes']
sector_data = {}
for sector in sectors:
sector_emissions = df2[(df2['Sector'] == sector) &
(df2['Country'] == 'GLOBAL TOTAL')]
sector_data[sector] = sector_emissions[list(years_covid)].values[0]
# Create DataFrame for plotly
df_sectors = pd.DataFrame(sector_data, index=years_covid).reset_index()
df_sectors_melted = df_sectors.melt('index', var_name='Sector',
value_name='Emissions')
fig_sectors = px.line(
df_sectors_melted,
x='index',
y='Emissions',
color='Sector',
title='CO2 Emissions by Sector Around COVID-19'
)
fig_sectors.add_vline(x=2020, line_dash="dash", line_color="red",
annotation_text="COVID-19")
st.plotly_chart(fig_sectors, use_container_width=True)
# Display sector-specific impacts
st.subheader("Sector Impact (2019-2020)")
cols = st.columns(len(sectors))
for i, sector in enumerate(sectors):
change = ((sector_data[sector][3] - sector_data[sector][2])/
sector_data[sector][2]*100)
cols[i].metric(sector, f"{change:.1f}%")
def create_agreements_timeline(df1):
# Get the global total data
global_data = df1[df1['Country'] == 'GLOBAL TOTAL'].iloc[0]
# Get only the year columns (1970 to 2023)
year_columns = [col for col in df1.columns if str(col).isdigit()]
years = [int(col) for col in year_columns]
values = [global_data[year] for year in years]
# Create the plot using plotly
fig = px.line(
x=years,
y=values,
title='Global CO2 Emissions and Key Climate Agreements',
labels={'x': 'Year', 'y': 'CO2 Emissions (Mt CO2)'}
)
# Add vertical lines for key agreements
agreements = {
1997: 'Kyoto Protocol Adopted',
2005: 'Kyoto Protocol Enforced',
2015: 'Paris Agreement'
}
colors = {'1997': 'red', '2005': 'green', '2015': 'orange'}
for year, agreement in agreements.items():
fig.add_vline(
x=year,
line_dash="dash",
line_color=colors[str(year)],
annotation_text=agreement,
annotation_position="top"
)
# Customize layout
fig.update_layout(
hovermode='x unified',
showlegend=False,
height=600
)
return fig
# Main App Function
def main():
st.set_page_config(page_title="CO2 Emissions Dashboard", layout="wide")
st.title("Global CO2 Emissions Dashboard")
# Load Data
df1 = load_data("fossil_CO2_per_capita_by_countr")
df2 = load_data("fossil_CO2_totals_by_country")
df3 = load_data("fossil_CO2_by_sector_country_su", year_range=(2017, 2023), sector="Sector")
df_covid = load_data("fossil_CO2_totals_by_country", year_range=(2017, 2023))
df_poliicy = load_data("fossil_CO2_totals_by_country", year_range=(1970,2023))
df2 = df2[df2['Country'] != 'International Shipping']
df_only_countries = df2.copy()[:210]
# Sidebar Controls
#st.sidebar.header("Controls")
#st.sidebar.markdown("---")
st.sidebar.image("dati/SIAM-logo.jpg", width=150)
visualization_type = st.sidebar.radio(
"Choose Visualization",
["Time Series Plot", "Animated World Map", "Bar Chart Race", "COVID-19 Impact", "Climate Agreements Timeline"]
)
# Year range selector (common to both visualizations)
year_range = st.sidebar.slider(
"Select Year Range",
min_value=YEAR_RANGE[0],
max_value=YEAR_RANGE[1],
value=YEAR_RANGE
)
# Conditional controls and display
if visualization_type == "Time Series Plot":
st.subheader("CO2 Emissions Time Series")
# Show country selector only for time series
countries = df1['Country'].unique().tolist()
selected_countries = st.sidebar.multiselect(
"Select countries to compare",
options=countries,
default=DEFAULT_COUNTRIES
)
# Process and display time series plot
df_processed = process_data_for_line_plot(df1, selected_countries, year_range)
fig = create_line_plot(df_processed)
st.plotly_chart(fig, use_container_width=True)
elif visualization_type == "Animated World Map":
st.subheader("Global Emissions Map (Animated)")
fig_map = create_animated_choropleth(df1, year_range[0], year_range[1])
st.plotly_chart(fig_map, use_container_width=True)
elif visualization_type == "Climate Agreements Timeline":
st.subheader("Global Emissions and Climate Agreements")
# Add some context about the agreements
with st.expander("About the Climate Agreements"):
st.markdown("""
- **Kyoto Protocol (1997)**: First legally binding agreement to reduce greenhouse gases
- **Kyoto Protocol Enforcement (2005)**: The protocol came into force
- **Paris Agreement (2015)**: Global agreement to limit temperature rise to well below 2°C
""")
# Create and display the plot
fig = create_agreements_timeline(df_poliicy)
st.plotly_chart(fig, use_container_width=True)
# Add some analysis
st.markdown("### Key Observations")
col1, col2, col3 = st.columns(3)
# Calculate some metrics
kyoto_change = ((float(df_poliicy[df_poliicy['Country'] == 'GLOBAL TOTAL'][2005]) -
float(df_poliicy[df_poliicy['Country'] == 'GLOBAL TOTAL'][1997])) /
float(df_poliicy[df_poliicy['Country'] == 'GLOBAL TOTAL'][1997]) * 100)
paris_change = ((float(df_poliicy[df_poliicy['Country'] == 'GLOBAL TOTAL'][2023]) -
float(df_poliicy[df_poliicy['Country'] == 'GLOBAL TOTAL'][2015])) /
float(df_poliicy[df_poliicy['Country'] == 'GLOBAL TOTAL'][2015]) * 100)
with col1:
st.metric("Emissions Change 1997-2005", f"{kyoto_change:.1f}%")
with col2:
st.metric("Emissions Change 2015-2023", f"{paris_change:.1f}%")
with col3:
latest_emissions = float(df_poliicy[df_poliicy['Country'] == 'GLOBAL TOTAL'][2023])
st.metric("Current Emissions (Mt CO2)", f"{latest_emissions:.1f}")
elif visualization_type == "COVID-19 Impact":
st.subheader("COVID-19 Impact Analysis")
create_covid_impact_plot(df_covid, df3)
else:
st.subheader("Top 10 CO2 Emitters Race")
fig_race = create_race_plot(df_only_countries, year_range)
st.plotly_chart(fig_race, use_container_width=True)
st.sidebar.markdown("---")
st.sidebar.markdown(""" GRUPPO 5 (EMANUELA, FULVIO, MARCO, TINSAE) """)
if __name__ == "__main__":
main()