|
|
|
|
|
import altair as alt |
|
|
import pandas as pd |
|
|
import streamlit as st |
|
|
|
|
|
|
|
|
def plot_actual_vs_predicted(df: pd.DataFrame): |
|
|
if "Product_Store_Sales_Total" not in df.columns or "Predicted_Sales" not in df.columns: |
|
|
st.warning("ℹ️ Required columns not found for plotting.") |
|
|
return |
|
|
|
|
|
plot_df = df[["Product_Store_Sales_Total", "Predicted_Sales"]].dropna() |
|
|
|
|
|
if plot_df.empty: |
|
|
st.info("ℹ️ Not enough valid rows for plotting.") |
|
|
return |
|
|
|
|
|
x_min = plot_df["Product_Store_Sales_Total"].min() |
|
|
x_max = plot_df["Product_Store_Sales_Total"].max() |
|
|
|
|
|
|
|
|
scatter = alt.Chart(plot_df).mark_circle(size=60, color='steelblue').encode( |
|
|
x=alt.X("Product_Store_Sales_Total", title="Actual Sales"), |
|
|
y=alt.Y("Predicted_Sales", title="Predicted Sales"), |
|
|
tooltip=["Product_Store_Sales_Total", "Predicted_Sales"] |
|
|
) |
|
|
|
|
|
|
|
|
parity_line = alt.Chart(pd.DataFrame({ |
|
|
'x': [x_min, x_max], |
|
|
'y': [x_min, x_max] |
|
|
})).mark_line(color='red', strokeDash=[5, 5]).encode( |
|
|
x='x:Q', |
|
|
y='y:Q' |
|
|
) |
|
|
|
|
|
|
|
|
chart = (scatter + parity_line).properties( |
|
|
width=700, |
|
|
height=400, |
|
|
title="Actual vs Predicted Sales" |
|
|
).configure_title(fontSize=18, anchor='middle') |
|
|
|
|
|
st.altair_chart(chart, use_container_width=True) |
|
|
|
|
|
|