demo / app.py
kiranzxy007's picture
Update app.py
d8d88fb verified
raw
history blame
6.1 kB
import streamlit as st
import pandas as pd
import numpy as np
from bokeh.plotting import figure
from bokeh.layouts import column, layout
from bokeh.models import ColumnDataSource, HoverTool, NumeralTickFormatter, Range1d, Div
from bokeh.palettes import Category20, RdYlGn
from bokeh.themes import Theme
from datetime import datetime
# Function to generate Bokeh plots
def generate_dashboard():
# Read and process the data
data = pd.read_csv("data.csv")
data['Date'] = pd.to_datetime(data['Date'])
# Sort the data by date
data = data.sort_values('Date')
# Get the latest two dates
latest_date = data['Date'].max()
previous_date = data[data['Date'] < latest_date]['Date'].max()
# Filter data for the latest two dates
latest_data = data[data['Date'] == latest_date]
previous_data = data[data['Date'] == previous_date]
# Define the metrics for percentage change calculation
change_metrics = [
'Installation Status',
'Inspection Approved Status',
'Application Status',
'Inspection Rejected Status',
'Subsidy Redeem Status (Amount)'
]
# Calculate percentage change
def calculate_percentage_change(state, metric):
latest_value = latest_data[latest_data['State'] == state][metric].values[0]
previous_value = previous_data[previous_data['State'] == state][metric].values[0]
if previous_value == 0 and latest_value == 0:
return 0
elif previous_value == 0:
return 100 if latest_value > 0 else 0
return ((latest_value - previous_value) / previous_value) * 100
# Create DataFrames with percentage changes
change_data = {}
for metric in change_metrics:
change_data[metric] = pd.DataFrame({
'State': latest_data['State'],
'Percentage_Change': latest_data['State'].apply(lambda x: calculate_percentage_change(x, metric))
})
change_data[metric] = change_data[metric].sort_values('Percentage_Change', ascending=False)
def create_percentage_change_figure(title, data, metric):
source = ColumnDataSource(data)
colors = [RdYlGn[11][5] if x == 0 else RdYlGn[11][0] if x > 0 else RdYlGn[11][10] for x in data['Percentage_Change']]
source.add(colors, 'color')
p = figure(title=title, x_range=data['State'].tolist(), height=400, width=1000, toolbar_location="above", tools="pan,wheel_zoom,box_zoom,reset,save")
p.vbar(x='State', top='Percentage_Change', width=0.9, source=source, line_color='white', fill_color='color')
p.xgrid.grid_line_color = None
max_change = max(abs(data['Percentage_Change'].max()), abs(data['Percentage_Change'].min()))
p.y_range = Range1d(-max_change * 1.1, max_change * 1.1)
p.xaxis.axis_label = "State"
p.yaxis.axis_label = "Percentage Change"
p.xaxis.major_label_orientation = 0.7
p.yaxis.formatter = NumeralTickFormatter(format="0,0.00")
p.title.text_font_size = "12pt"
p.xaxis.axis_label_text_font_size = "10pt"
p.yaxis.axis_label_text_font_size = "10pt"
p.xaxis.major_label_text_font_size = "8pt"
p.yaxis.major_label_text_font_size = "8pt"
hover = HoverTool(tooltips=[("State", "@State"), ("Percentage Change", "@Percentage_Change{0.00}%")])
p.add_tools(hover)
return p
def create_state_figure(title, x_range, source, metric):
p = figure(title=title, x_range=x_range, height=400, width=900, toolbar_location="above", tools="pan,wheel_zoom,box_zoom,reset,save")
p.vbar(x='State', top=metric, width=0.9, source=source, line_color='white', fill_color='color')
p.xgrid.grid_line_color = None
p.y_range.start = 0
p.xaxis.axis_label = "State"
p.yaxis.axis_label = "Count"
p.xaxis.major_label_orientation = 0.7
p.yaxis.formatter = NumeralTickFormatter(format="0,0")
p.title.text_font_size = "12pt"
p.xaxis.axis_label_text_font_size = "10pt"
p.yaxis.axis_label_text_font_size = "10pt"
p.xaxis.major_label_text_font_size = "8pt"
p.yaxis.major_label_text_font_size = "8pt"
hover = HoverTool(tooltips=[("State", "@State"), (metric, f"@{{{metric}}}")])
p.add_tools(hover)
return p
# Create percentage change figures
change_figures = {}
for metric in change_metrics:
change_figures[metric] = create_percentage_change_figure(f"Day-on-Day Percentage Change - {metric}", change_data[metric], metric)
# Create state figures
state_metrics = [
'Application Status',
'Installation Status',
'Inspection Approved Status',
'Subsidy Redeem Status'
]
figures = {}
for metric in state_metrics:
sorted_data = latest_data.sort_values(by=metric, ascending=False)
top_states = sorted_data.head(10)['State'].tolist()
bottom_states = sorted_data.tail(10)['State'].tolist()[::-1]
for suffix, states in [('top', top_states), ('bottom', bottom_states)]:
source = ColumnDataSource(latest_data[latest_data['State'].isin(states)])
source.data['color'] = Category20[20][:10] if suffix == 'top' else Category20[20][10:]
key = f"{metric}_{suffix}"
figures[key] = create_state_figure(f"{'Top' if suffix == 'top' else 'Bottom'} 10 States - {metric}", states, source, metric)
return figures, change_figures
# Streamlit application
st.set_page_config(page_title="State Statistics Dashboard", layout="wide")
st.title("State Statistics Dashboard")
st.markdown(f"<p style='text-align: center; font-style: italic;'>Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>", unsafe_allow_html=True)
# Generate the dashboard figures
figures, change_figures = generate_dashboard()
# Display the Bokeh plots in Streamlit
for metric in figures:
st.bokeh_chart(figures[metric], use_container_width=True)
for metric in change_figures:
st.bokeh_chart(change_figures[metric], use_container_width=True)