import gradio as gr import yfinance as yf import pandas as pd import plotly.graph_objects as go from typing import Tuple, Optional import logging # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Mapping company names to their ticker symbols COMPANY_DICT = { "Apple": "AAPL", "Google": "GOOGL", "Microsoft": "MSFT", "Amazon": "AMZN", "Tesla": "TSLA", "Meta": "META", "NVIDIA": "NVDA", "Netflix": "NFLX" } def create_line_plot(df: pd.DataFrame, company_name: str) -> go.Figure: """Create a line plot using plotly""" fig = go.Figure() fig.add_trace(go.Scatter( x=df["ESG Category"], y=df["Score"], mode='lines+markers', name='ESG Score', line=dict(color='rgb(55, 83, 109)', width=2), marker=dict(size=10) )) fig.update_layout( title=f"ESG Scores Trend for {company_name}", xaxis_title="ESG Category", yaxis_title="Score", yaxis_range=[0, 100], height=400, template='plotly_white' ) return fig def create_scatter_plot(df: pd.DataFrame, company_name: str) -> go.Figure: """Create a scatter plot using plotly""" fig = go.Figure() fig.add_trace(go.Scatter( x=df["ESG Category"], y=df["Score"], mode='markers', marker=dict( size=15, color='rgb(55, 83, 109)', line=dict( color='rgb(8,48,107)', width=2 ) ), name='ESG Score' )) fig.update_layout( title=f"ESG Score Distribution for {company_name}", xaxis_title="ESG Category", yaxis_title="Score", yaxis_range=[0, 100], height=400, template='plotly_white' ) return fig def create_bar_plot(df: pd.DataFrame, company_name: str) -> go.Figure: """Create a bar plot using plotly""" fig = go.Figure() fig.add_trace(go.Bar( x=df["ESG Category"], y=df["Score"], marker_color='rgb(55, 83, 109)', name='ESG Score' )) fig.update_layout( title=f"ESG Scores Comparison for {company_name}", xaxis_title="ESG Category", yaxis_title="Score", yaxis_range=[0, 100], height=400, template='plotly_white' ) return fig def create_pie_chart(df: pd.DataFrame, company_name: str) -> go.Figure: """Create a pie chart using plotly""" total_score = df['Score'].sum() percentages = (df['Score'] / total_score * 100).round(1) # Create labels with both category and percentage labels = [f"{cat} ({pct}%)" for cat, pct in zip(df['ESG Category'], percentages)] fig = go.Figure() fig.add_trace(go.Pie( labels=labels, values=df['Score'], hole=0.4, # Creates a donut chart marker=dict( colors=['rgb(55, 83, 109)', 'rgb(26, 118, 255)', 'rgb(178, 200, 223)'] ), textinfo='label+value', textposition='outside', texttemplate='%{label}
Score: %{value:.1f}' )) fig.update_layout( title=f"ESG Score Distribution for {company_name}", height=400, template='plotly_white', showlegend=False ) return fig def create_empty_plot(message: str) -> go.Figure: """Create an empty plot with an error message""" fig = go.Figure() fig.add_annotation( text=message, xref="paper", yref="paper", x=0.5, y=0.5, showarrow=False, font=dict(size=14) ) fig.update_layout( xaxis_visible=False, yaxis_visible=False, height=400 ) return fig def fetch_esg_data(company_name: str) -> Tuple[Optional[pd.DataFrame], str]: """ Fetch and process ESG data for the selected company. """ try: ticker = COMPANY_DICT[company_name] logger.info(f"Fetching ESG data for {company_name} ({ticker})") stock = yf.Ticker(ticker) esg_data = stock.sustainability if esg_data is None: return None, f"No ESG data available for {company_name}" esg_df = pd.DataFrame(esg_data) esg_scores = esg_df.loc[["environmentScore", "socialScore", "governanceScore"], :].dropna().astype(float) plot_df = pd.DataFrame({ "ESG Category": ["Environment", "Social", "Governance"], "Score": esg_scores.squeeze().values }) return plot_df, f"Successfully fetched ESG data for {company_name}" except Exception as e: logger.error(f"Error fetching ESG data: {str(e)}") return None, f"Error fetching ESG data: {str(e)}" def create_interface() -> gr.Blocks: """Create the Gradio interface""" with gr.Blocks(theme=gr.themes.Soft()) as app: gr.Markdown("# ESG Data Visualization Dashboard") gr.Markdown("Analyze Environmental, Social, and Governance scores for major tech companies.") with gr.Tab("ESG Analysis"): with gr.Row(): with gr.Column(): company = gr.Dropdown( label="Select Company", choices=list(COMPANY_DICT.keys()), value="Apple" ) plot_button = gr.Button("Generate ESG Analysis", variant="primary") status_message = gr.Textbox( label="Status", interactive=False, visible=True ) with gr.Row(): with gr.Column(): line_plot = gr.Plot(label="Trend Analysis") with gr.Column(): pie_plot = gr.Plot(label="Distribution Analysis") with gr.Row(): with gr.Column(): scatter_plot = gr.Plot(label="Score Distribution") with gr.Column(): bar_plot = gr.Plot(label="Score Comparison") def process_esg_request(company_name: str) -> Tuple[go.Figure, go.Figure, go.Figure, go.Figure, str]: # Fetch the data plot_df, status = fetch_esg_data(company_name) if plot_df is None: empty_plot = create_empty_plot(status) return empty_plot, empty_plot, empty_plot, empty_plot, status # Create all plots line = create_line_plot(plot_df, company_name) scatter = create_scatter_plot(plot_df, company_name) bar = create_bar_plot(plot_df, company_name) pie = create_pie_chart(plot_df, company_name) return line, pie, scatter, bar, status # Connect the button click to the process function plot_button.click( fn=process_esg_request, inputs=company, outputs=[line_plot, pie_plot, scatter_plot, bar_plot, status_message], api_name="generate_esg_analysis" ) with gr.Tab("About"): gr.Markdown(""" ## About This Dashboard This dashboard provides ESG (Environmental, Social, and Governance) data visualization for major technology companies. The data is sourced from Yahoo Finance and updated regularly. ### How to Use 1. Select a company from the dropdown menu 2. Click 'Generate ESG Analysis' to view multiple visualizations: - Trend Analysis: Shows the progression across ESG categories - Distribution Analysis: Shows the relative proportion of each ESG component - Score Distribution: Displays the spread of ESG scores - Score Comparison: Compares ESG scores side by side ### Metrics Explained - **Environmental Score**: Measures company's environmental impact and sustainability initiatives - **Social Score**: Evaluates company's relationships with employees, suppliers, customers, and communities - **Governance Score**: Assesses company's leadership, executive pay, audits, internal controls, and shareholder rights """) return app if __name__ == "__main__": app = create_interface() app.launch(share=True, debug=True)