|
import streamlit as st
|
|
from streamlit_option_menu import option_menu
|
|
import streamlit_shadcn_ui as ui
|
|
from streamlit_echarts import st_echarts
|
|
import numpy as np
|
|
import pandas as pd
|
|
import seaborn as sns
|
|
import matplotlib.pyplot as plt
|
|
import folium
|
|
from streamlit_folium import st_folium
|
|
import plotly.express as px
|
|
import base64
|
|
import pickle
|
|
import time
|
|
from datetime import datetime
|
|
from pycaret.regression import load_model, predict_model
|
|
|
|
|
|
st.set_page_config(
|
|
page_title="WALPA - Walmart Prediction App",
|
|
page_icon="🧊",
|
|
layout="wide",
|
|
initial_sidebar_state="expanded",
|
|
)
|
|
@st.cache_data
|
|
def load_data(dataset):
|
|
df = pd.read_csv(dataset)
|
|
return df
|
|
def csvdownload(df):
|
|
csv = df.to_csv(index=False)
|
|
b64 = base64.b64encode(csv.encode()).decode()
|
|
href = f'<a href="data:file/csv;base64,{b64}" download="{df}_prediction.csv">Download CSV File</a>'
|
|
return href
|
|
def autoplay_audio(file_path: str):
|
|
with open(file_path, "rb") as f:
|
|
data = f.read()
|
|
b64 = base64.b64encode(data).decode()
|
|
md = f"""
|
|
<audio controls autoplay="true">
|
|
<source src="data:audio/wav;base64,{b64}" type="audio/wav">
|
|
</audio>
|
|
"""
|
|
st.markdown(
|
|
md,
|
|
unsafe_allow_html=True,
|
|
)
|
|
|
|
data = load_data('./datasets/Walmart.csv')
|
|
sumSales = data['Daily_Sales'].sum()
|
|
sumUnem = data['Unemployment'].sum()
|
|
def sum_Sales():
|
|
if sumSales > 999 and sumSales < 9999:
|
|
sum_display = "$" + str(sumSales)[:1] + "K"
|
|
elif sumSales > 9999 and sumSales < 99999:
|
|
sum_display = "$" + str(sumSales)[:2] + "K"
|
|
elif sumSales > 99999 and sumSales < 999999:
|
|
sum_display = "$" + str(sumSales)[:3] + "K"
|
|
elif sumSales > 999999 and sumSales < 9999999:
|
|
sum_display = "$" + str(sumSales)[:1] + "M"
|
|
elif sumSales > 9999999 and sumSales < 99999999:
|
|
sum_display = "$" + str(sumSales)[:2] + "M"
|
|
elif sumSales > 99999999 and sumSales < 999999999:
|
|
sum_display = "$" + str(sumSales)[:3] + "M"
|
|
elif sumSales > 999999999 and sumSales < 9999999999:
|
|
sum_display = "$" + str(sumSales)[:1] + "MD"
|
|
elif sumSales > 9999999999 and sumSales < 99999999999:
|
|
sum_display = "$" + str(sumSales)[:2] + "MD"
|
|
elif sumSales > 99999999999 and sumSales < 99999999999:
|
|
sum_display = "$" + str(sumSales)[:3] + "MD"
|
|
elif sumSales > 999999999999 and sumSales < 999999999999:
|
|
sum_display = "$" + str(sumSales)[:4] + "MD"
|
|
return sum_display
|
|
|
|
def sumUnemp():
|
|
if sumUnem > 999 and sumUnem < 9999:
|
|
sum_Unem = str(sumUnem)[:1] + "K"
|
|
elif sumUnem > 9999 and sumUnem < 99999:
|
|
sum_Unem = str(sumUnem)[:2] + "K"
|
|
elif sumUnem > 99999 and sumUnem < 999999:
|
|
sum_Unem = str(sumUnem)[:3] + "K"
|
|
elif sumUnem > 999999 and sumUnem < 9999999:
|
|
sum_Unem = str(sumUnem)[:1] + "M"
|
|
elif sumUnem > 9999999 and sumUnem < 99999999:
|
|
sum_Unem = str(sumUnem)[:2] + "M"
|
|
elif sumUnem > 99999999 and sumUnem < 999999999:
|
|
sum_Unem = str(sumUnem)[:3] + "M"
|
|
elif sumUnem > 999999999 and sumUnem < 9999999999:
|
|
sum_Unem = str(sumUnem)[:1] + "MD"
|
|
elif sumUnem > 9999999999 and sumUnem < 99999999999:
|
|
sum_Unem = str(sumUnem)[:2] + "MD"
|
|
elif sumUnem > 99999999999 and sumUnem < 99999999999:
|
|
sum_Unem = str(sumUnem)[:3] + "MD"
|
|
elif sumUnem > 999999999999 and sumUnem < 999999999999:
|
|
sum_Unem = str(sumUnem)[:4] + "MD"
|
|
return sum_Unem
|
|
|
|
def main():
|
|
with st.sidebar:
|
|
|
|
selected = option_menu("Main Menu", ['Home', 'Dashboard', 'Analysis', 'Visualization', 'Machine Learning'],
|
|
icons=['house','speedometer2', 'boxes', 'graph-up-arrow', 'easel2'], menu_icon="list", default_index=0,
|
|
styles={
|
|
"container": {"padding": "5px", "background-color": "transparent", "font-weight": "bold"},
|
|
"icon": {"font-size": "17px"},
|
|
"nav-link": {"font-size": "15px", "text-align": "left", "margin":"5px","padding": "10px", "--hover-color": "#1E90FF"},
|
|
"nav-link-selected": {"background-color": "#1E90FF"},
|
|
}
|
|
)
|
|
|
|
left,middle,right = st.columns((0.5,4,0.5))
|
|
if selected == 'Home':
|
|
with middle:
|
|
col1, col2, col3 = st.columns(3)
|
|
with col2:
|
|
st.image('./assets/images/walpa-logo.png')
|
|
st.subheader('What is Walpa ?')
|
|
st.write("Walpa is a Streamlit Machine Learning App created to assist data engineers in multiple tasks such as datasets Analysis report, visualization, and predictions for the case of Walmart Inc.")
|
|
st.write("This is not an official Walmart Inc app is just for educational purpose")
|
|
st.subheader("Walpa's Team")
|
|
team = [
|
|
{"role": "Founder", "name": "Jason Ntone"},
|
|
{"role": "Developer", "name": "Jason Ntone"},
|
|
{"role": "Designer", "name": "Jason Ntone"}
|
|
]
|
|
st.write(team)
|
|
st.markdown(" - All rights reserved WALPA\u00A9")
|
|
elif selected == 'Dashboard':
|
|
|
|
with middle:
|
|
col1, col2, col3 = st.columns(3)
|
|
with col2:
|
|
st.image('./assets/images/walpa-logo.png')
|
|
st.title("Walmart Dashboard")
|
|
col4, col5, col6 = st.columns(3)
|
|
with col4:
|
|
temp = st.metric(label="Total Sales", value=sum_Sales(), delta="From 5010 To 2012")
|
|
with col5:
|
|
temp = st.metric(label="Total Unemployemt", value=sumUnemp(), delta="From 2010 To 2012")
|
|
with col6:
|
|
temp = st.metric(label="Total Stores studied", value=45, delta="From 2010 To 2012")
|
|
|
|
with middle:
|
|
st.subheader("Walmart Stores Map")
|
|
|
|
stores = data['Store'].unique()
|
|
longitude_values = [-111.0327, -88.1668, -121.3477, -77.0891, -87.3695, -95.3271, -79.2854, -84.3594, -81.5951, -82.7852, -118.5694, -82.2711, -80.6665, -78.2971, -103.3284, -84.8482, -93.0727, -117.0266, -97.0088, -82.1349, -76.8572, -104.7973, -123.2838, -91.5127, -117.3879, -97.9895, -80.2403, -82.0174, -94.6041, -117.0774, -88.2285, -81.4383, -83.3702, -93.2422, -100.4930, -81.8765, -85.4835, -117.0731, -79.7245, -86.2356, -75.7216, -90.1516, -77.8990, -86.2169, -96.6857]
|
|
latitude_values = [32.1555, 39.4931, 37.9886, 38.7684, 36.5298, 29.5636, 33.3776, 33.7603, 31.8469, 39.9673, 34.2801, 27.9944, 37.1505, 36.0659, 34.1866, 37.8041, 44.8955, 32.9759, 30.6631, 33.5412, 39.6366, 41.1364, 44.5714, 31.5634, 34.1041, 26.1536, 39.0212, 38.9188, 38.8837, 32.6389, 42.9937, 30.2862, 33.3263, 45.1571, 28.7043, 27.2008, 39.3378, 32.6072, 39.9002, 32.3838, 40.8332, 32.4081, 34.1641, 32.3418, 40.7399]
|
|
|
|
|
|
wmap = folium.Map(location=[37.0902, -95.7129], zoom_start=4)
|
|
|
|
|
|
for store, lon, lat in zip(stores, longitude_values, latitude_values):
|
|
folium.Marker([lat, lon], popup=store,icon=folium.Icon(color='blue', icon='shopping-cart', prefix='fa')).add_to(wmap)
|
|
|
|
|
|
wmap.fit_bounds([[24.396308, -125.000000], [49.384358, -66.934570]])
|
|
|
|
st_data = st_folium(wmap, width=800)
|
|
elif selected == 'Analysis':
|
|
with middle:
|
|
col1,col2,col3 = st.columns((0.5,3,0.5))
|
|
with col2:
|
|
tab = ui.tabs(options=['Overview', 'Sumary', 'Correlation Matrix'], default_value='Overview', key="none")
|
|
st.title("Data Analysis")
|
|
if tab == 'Overview':
|
|
st.subheader('Walmart Daily Sales Overview')
|
|
st.dataframe(data.head())
|
|
elif tab == 'Sumary':
|
|
st.subheader('Walmart Daily Sales Sumary')
|
|
st.dataframe(data.describe())
|
|
elif tab == 'Correlation Matrix':
|
|
st.subheader('Walmart Correlation Matrix')
|
|
fig = plt.figure(figsize=(15,5))
|
|
st.write(sns.heatmap(data.corr(),annot=True))
|
|
st.pyplot(fig)
|
|
elif selected == 'Visualization':
|
|
with middle:
|
|
tab = ui.tabs(options=['Regplot', 'Barplot', 'Lineplot'], default_value='Barplot', key="none")
|
|
if tab == 'Regplot':
|
|
st.subheader('Walmart Daily Sales Regplot')
|
|
fig = plt.figure(figsize=(15,5))
|
|
st.write(sns.regplot(data=data, x='Store', y='Daily_Sales'))
|
|
st.pyplot(fig)
|
|
elif tab == 'Barplot':
|
|
st.subheader('Walmart Daily Sales Barplot')
|
|
option = {
|
|
"xAxis": {
|
|
"type": "category",
|
|
"data": data['Store'].tolist(),
|
|
},
|
|
"yAxis": {
|
|
"type": "value"
|
|
},
|
|
"series": [{
|
|
"data": data['Daily_Sales'].tolist(),
|
|
"type": "bar"
|
|
}]
|
|
}
|
|
st_echarts(
|
|
options=option,
|
|
height="400px",
|
|
)
|
|
elif tab == 'Lineplot':
|
|
st.subheader('Walmart Daily Sales line plot')
|
|
option = {
|
|
"xAxis": {
|
|
"type": "category",
|
|
"data": data['Date'].tolist(),
|
|
},
|
|
"yAxis": {
|
|
"type": "value"
|
|
},
|
|
"series": [{
|
|
"data": data['Daily_Sales'].tolist(),
|
|
"type": "line"
|
|
}]
|
|
}
|
|
st_echarts(
|
|
options=option,
|
|
height="400px",
|
|
)
|
|
|
|
elif selected == 'Machine Learning':
|
|
with middle:
|
|
st.subheader('📈🎯 Daily Sales Prediction Widget')
|
|
tab = ui.tabs(options=['Method 1: Upload Dataset', 'Method 2: Fill the form'], default_value='Fill the form', key="none")
|
|
st.write('\n')
|
|
if tab == 'Method 2: Fill the form':
|
|
st.markdown('**Fill the form with correct data to make prediction**')
|
|
col1,col2,col3 = st.columns(3)
|
|
with col1:
|
|
|
|
st.write('Enter the Year')
|
|
year = ui.input(type='number', default_value=0, key="year")
|
|
with col2:
|
|
st.write('Enter the Month')
|
|
month = ui.input(type='number', default_value=0, key="month")
|
|
with col3:
|
|
st.write('Enter the Day')
|
|
day = ui.input(type='number', default_value=0, key="day")
|
|
|
|
|
|
st.write('Enter Store Number')
|
|
store = ui.input(type='number', default_value=0, key="input1")
|
|
|
|
st.write(f'The date : **{year}-{month}-{day}** you have entered is that a holiday ?')
|
|
holiday = [
|
|
{"label": "Yes", "value": 1, "id": "r1"},
|
|
{"label": "No", "value": 0, "id": "r2"},
|
|
]
|
|
holiday_flag = ui.radio_group(options=holiday, default_value=0, key="radio1")
|
|
|
|
col3,col4 = st.columns((2,2))
|
|
with col3:
|
|
st.write('Enter the Temperature')
|
|
temperature = ui.input(type='text', default_value=0, key="input2")
|
|
|
|
with col4:
|
|
st.write('Enter the Fuel Price')
|
|
fuel_price = ui.input(type='text', default_value=0, key="input3")
|
|
|
|
col5,col6 = st.columns((2,2))
|
|
with col5:
|
|
st.write('Enter the CPI')
|
|
cpi = ui.input(type='text', default_value=0, key="input4")
|
|
|
|
with col6:
|
|
st.write('Enter the Unemployment')
|
|
unemployment = ui.input(type='text', default_value=0, key="input5")
|
|
|
|
Store= int(store)
|
|
Holiday_Flag= int(holiday_flag)
|
|
Temperature= float(temperature)
|
|
Fuel_Price= float(fuel_price)
|
|
CPI= float(cpi)
|
|
Unemployment= float(unemployment)
|
|
Year = int(year)
|
|
Month = int(month)
|
|
Day = int(day)
|
|
form_data = pd.DataFrame([[Store, Holiday_Flag, Temperature, Fuel_Price, CPI, Unemployment, Year, Month, Day]],
|
|
columns=['Store', 'Holiday_Flag', 'Temperature',
|
|
'Fuel_Price', 'CPI', 'Unemployment','Year', 'Month', 'Day'])
|
|
st.subheader('Your provided data')
|
|
st.dataframe(form_data)
|
|
submit_btn = ui.button(text="Predict Daily Sales", key="styled_btn_tailwind", className="bg-blue-500 text-white")
|
|
if submit_btn:
|
|
if form_data.empty == False:
|
|
model_path = './models/Walmart'
|
|
model = load_model(model_path)
|
|
|
|
|
|
pred = predict_model(model, data=form_data)
|
|
|
|
prediction = pred['prediction_label'].values[0]
|
|
|
|
|
|
with st.status("Daily Sales Prediction processing...", expanded=True) as status:
|
|
st.write("Handling data...")
|
|
time.sleep(2)
|
|
st.write("Load Model...")
|
|
time.sleep(1)
|
|
st.write("Load Data...")
|
|
time.sleep(1)
|
|
status.update(label="Daily Sales Prediction processing complete!", state="complete", expanded=False)
|
|
autoplay_audio("./assets/audio/mixkit-positive-notification-951.wav")
|
|
st.success(prediction)
|
|
else:
|
|
st.warning("Fill the form")
|
|
if tab == 'Method 1: Upload Dataset':
|
|
with middle:
|
|
st.header("Load your file")
|
|
uploaded_file = st.file_uploader('Upload your Dataset(.csv file)',
|
|
type=['csv'])
|
|
if uploaded_file:
|
|
df = load_data(uploaded_file)
|
|
df['Year'] = pd.to_datetime(df['Date']).dt.year
|
|
df['Month'] = pd.to_datetime(df['Date']).dt.month
|
|
df['Day'] = pd.to_datetime(df['Date']).dt.day
|
|
df = df.drop(['Date'], axis=1)
|
|
model_path = './models/Walmart'
|
|
model = load_model(model_path)
|
|
preds = predict_model(model, data=df)
|
|
|
|
predictions = preds['prediction_label'].values
|
|
|
|
|
|
pp = pd.DataFrame(predictions, columns=['Daily_Sales_Prediction'])
|
|
|
|
ndf = pd.concat([df, pp], axis=1)
|
|
st.subheader("Daily_Sales Predictions")
|
|
with st.status("Daily Sales Prediction processing...", expanded=True) as status:
|
|
st.write("Handling data...")
|
|
time.sleep(2)
|
|
st.write("Load Model...")
|
|
time.sleep(1)
|
|
st.write("Load Data...")
|
|
time.sleep(1)
|
|
status.update(label="Daily Sales Prediction processing complete!", state="complete", expanded=False)
|
|
autoplay_audio("./assets/audio/mixkit-positive-notification-951.wav")
|
|
st.write(ndf)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|
|
|