G7-SE21-FoodDeliveryAnalytics / src /streamlit_app.py
jq7hh's picture
Upload streamlit_app.py
bc41d1a verified
import streamlit as st
import pandas as pd
import plotly.express as px
from pathlib import Path
st.set_page_config(
page_title="Food Delivery Analytics",
page_icon="🍔",
layout="wide"
)
def find_file(filename: str) -> Path:
candidates = [
Path("/app") / filename,
Path("/app/src") / filename,
Path(__file__).resolve().parent / filename,
Path(__file__).resolve().parent.parent / filename,
]
for path in candidates:
if path.exists():
return path
raise FileNotFoundError(
f"Could not find {filename}. Checked: " + ", ".join(str(p) for p in candidates)
)
@st.cache_data
def load_data():
real_df = pd.read_csv(find_file("real_world_driver_data.csv"))
metrics_df = pd.read_csv(find_file("synthetic_delivery_metrics.csv"))
reviews_df = pd.read_csv(find_file("synthetic_customer_reviews.csv"))
features_df = pd.read_csv(find_file("synthetic_driver_features.csv"))
monthly_df = pd.read_csv(find_file("synthetic_monthly_delivery_series.csv"))
return real_df, metrics_df, reviews_df, features_df, monthly_df
real_df, metrics_df, reviews_df, features_df, monthly_df = load_data()
monthly_df["month"] = pd.to_datetime(monthly_df["month"])
# KPIs
total_drivers = features_df["driver_id"].nunique()
total_deliveries = int(metrics_df["deliveries_completed"].sum())
avg_rating = round(features_df["Delivery_person_Ratings"].mean(), 2)
total_reviews = int(reviews_df.shape[0])
# Sidebar
st.sidebar.title("Filters")
city_options = ["All"] + sorted(features_df["City"].dropna().unique().tolist())
vehicle_options = ["All"] + sorted(features_df["Type_of_vehicle"].dropna().unique().tolist())
selected_city = st.sidebar.selectbox("City", city_options)
selected_vehicle = st.sidebar.selectbox("Vehicle Type", vehicle_options)
filtered_features = features_df.copy()
if selected_city != "All":
filtered_features = filtered_features[filtered_features["City"] == selected_city]
if selected_vehicle != "All":
filtered_features = filtered_features[filtered_features["Type_of_vehicle"] == selected_vehicle]
filtered_driver_ids = filtered_features["driver_id"].unique()
filtered_metrics = metrics_df[metrics_df["driver_id"].isin(filtered_driver_ids)].copy()
filtered_reviews = reviews_df[reviews_df["driver_id"].isin(filtered_driver_ids)].copy()
filtered_total_drivers = filtered_features["driver_id"].nunique()
filtered_total_deliveries = int(filtered_metrics["deliveries_completed"].sum()) if not filtered_metrics.empty else 0
filtered_avg_rating = round(filtered_features["Delivery_person_Ratings"].mean(), 2) if not filtered_features.empty else 0
filtered_total_reviews = int(filtered_reviews.shape[0])
# Header
st.markdown("""
<h1 style='text-align: center;'>🍔 Food Delivery Analytics Dashboard</h1>
<p style='text-align: center; font-size:18px;'>
Analyze driver performance, customer sentiment, and delivery trends
</p>
""", unsafe_allow_html=True)
st.markdown("---")
# KPI cards
col1, col2, col3, col4 = st.columns(4)
col1.metric("🚚 Drivers", filtered_total_drivers)
col2.metric("📦 Deliveries", f"{filtered_total_deliveries:,}")
col3.metric("⭐ Avg Rating", filtered_avg_rating)
col4.metric("💬 Reviews", f"{filtered_total_reviews:,}")
st.markdown("---")
tab1, tab2, tab3, tab4 = st.tabs([
"Overview",
"Driver Performance",
"Customer Reviews",
"Monthly Trends"
])
with tab1:
st.subheader("Dataset Overview")
st.write("This dashboard combines driver performance, delivery activity, and customer sentiment data.")
col_a, col_b = st.columns(2)
with col_a:
if not filtered_features.empty:
fig_overview_1 = px.histogram(
filtered_features,
x="performance_tier",
title="Performance Tier Distribution"
)
st.plotly_chart(fig_overview_1, use_container_width=True)
with col_b:
if not filtered_features.empty:
city_counts = filtered_features["City"].value_counts().reset_index()
city_counts.columns = ["City", "count"]
fig_overview_2 = px.bar(
city_counts,
x="City",
y="count",
title="Drivers by City"
)
st.plotly_chart(fig_overview_2, use_container_width=True)
st.markdown("### Data Preview")
st.dataframe(filtered_features.head(10), use_container_width=True)
with tab2:
st.subheader("Driver Performance")
if not filtered_features.empty:
top_drivers = filtered_features.sort_values("total_deliveries", ascending=False).head(10)
fig1 = px.bar(
top_drivers,
x="driver_id",
y="total_deliveries",
color="performance_tier",
title="Top 10 Drivers by Total Deliveries"
)
st.plotly_chart(fig1, use_container_width=True)
fig2 = px.scatter(
filtered_features,
x="avg_delivery_time",
y="Delivery_person_Ratings",
color="sentiment_label",
hover_name="driver_id",
title="Average Delivery Time vs Driver Rating"
)
st.plotly_chart(fig2, use_container_width=True)
else:
st.warning("No driver data available for the selected filters.")
with tab3:
st.subheader("Customer Reviews")
if not filtered_reviews.empty:
col_a, col_b = st.columns(2)
with col_a:
sentiment_counts = filtered_reviews["sentiment_label"].value_counts().reset_index()
sentiment_counts.columns = ["sentiment_label", "count"]
fig3 = px.pie(
sentiment_counts,
names="sentiment_label",
values="count",
title="Customer Review Sentiment Distribution"
)
st.plotly_chart(fig3, use_container_width=True)
with col_b:
avg_rating_by_sentiment = (
filtered_reviews.groupby("sentiment_label", as_index=False)["driver_rating"]
.mean()
)
fig4 = px.bar(
avg_rating_by_sentiment,
x="sentiment_label",
y="driver_rating",
title="Average Rating by Sentiment"
)
st.plotly_chart(fig4, use_container_width=True)
st.write("Sample reviews:")
st.dataframe(
filtered_reviews[["driver_id", "sentiment_label", "driver_rating", "review_text"]].head(15),
use_container_width=True
)
else:
st.warning("No review data available for the selected filters.")
with tab4:
st.subheader("Monthly Delivery Trends")
if not filtered_metrics.empty:
monthly_trend = (
filtered_metrics.groupby("month", as_index=False)["deliveries_completed"]
.sum()
.rename(columns={"deliveries_completed": "total_deliveries"})
)
monthly_trend["month"] = pd.to_datetime(monthly_trend["month"])
fig4 = px.line(
monthly_trend,
x="month",
y="total_deliveries",
markers=True,
title="Total Deliveries Over Time"
)
st.plotly_chart(fig4, use_container_width=True)
else:
st.warning("No monthly delivery data available for the selected filters.")
import requests
st.markdown("---")
st.subheader("🤖 AI Insight")
webhook_url = "https://jq7hhh.app.n8n.cloud/webhook/3dc59db1-0e3d-4b73-bdc1-bbe5168feb6f"
if st.button("Generate AI Insight", key="n8n_ai_insight_button"):
payload = {
"city": selected_city,
"vehicle_type": selected_vehicle,
"drivers": int(filtered_total_drivers),
"deliveries": int(filtered_total_deliveries),
"avg_rating": float(filtered_avg_rating),
"reviews": int(filtered_total_reviews)
}
try:
response = requests.post(webhook_url, json=payload, timeout=20)
if response.status_code == 200:
result = response.json()
st.success(result.get("Insight", "Insight generated successfully."))
else:
st.error(f"Webhook error: {response.status_code}")
st.write(response.text)
except Exception as e:
st.error(f"Request failed: {e}")