Spaces:
Build error
Build error
| 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 | |
| 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() |