Spaces:
Sleeping
Sleeping
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}<br>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) |