Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import requests | |
| import pandas as pd | |
| import numpy as np | |
| import plotly.express as px | |
| import plotly.graph_objects as go | |
| from datetime import datetime | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="SuperKart Sales Forecasting", | |
| page_icon="🛒", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| font-size: 3rem; | |
| color: #1f77b4; | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| .metric-card { | |
| background-color: #f0f2f6; | |
| padding: 1rem; | |
| border-radius: 0.5rem; | |
| border-left: 5px solid #1f77b4; | |
| } | |
| .prediction-result { | |
| background-color: #e8f5e8; | |
| padding: 1rem; | |
| border-radius: 0.5rem; | |
| border: 2px solid #28a745; | |
| text-align: center; | |
| margin: 1rem 0; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # API Configuration | |
| API_BASE_URL = "https://ananttripathiak-superkart-akt.hf.space/" # Replace with your actual URL | |
| # Helper functions | |
| def make_prediction(data): | |
| """Make prediction using the API""" | |
| try: | |
| response = requests.post(f"{API_BASE_URL}/predict", json=data, timeout=30) | |
| if response.status_code == 200: | |
| return response.json() | |
| else: | |
| return {"error": f"API Error: {response.status_code}"} | |
| except requests.exceptions.RequestException as e: | |
| return {"error": f"Connection Error: {str(e)}"} | |
| def make_batch_prediction(data_list): | |
| """Make batch prediction using the API""" | |
| try: | |
| response = requests.post(f"{API_BASE_URL}/batch_predict", | |
| json={"data": data_list}, timeout=60) | |
| if response.status_code == 200: | |
| return response.json() | |
| else: | |
| return {"error": f"API Error: {response.status_code}"} | |
| except requests.exceptions.RequestException as e: | |
| return {"error": f"Connection Error: {str(e)}"} | |
| # Main app | |
| def main(): | |
| # Header | |
| st.markdown('<h1 class="main-header">🛒 SuperKart Sales Forecasting</h1>', | |
| unsafe_allow_html=True) | |
| # Sidebar | |
| st.sidebar.title("Navigation") | |
| page = st.sidebar.selectbox("Choose a page", | |
| ["Single Prediction", "Batch Prediction", "Data Analysis", "About"]) | |
| if page == "Single Prediction": | |
| single_prediction_page() | |
| elif page == "Batch Prediction": | |
| batch_prediction_page() | |
| elif page == "Data Analysis": | |
| data_analysis_page() | |
| elif page == "About": | |
| about_page() | |
| def single_prediction_page(): | |
| st.header("Single Product Sales Prediction") | |
| st.markdown("Predict sales revenue for a single product-store combination.") | |
| col1, col2 = st.columns([1, 1]) | |
| with col1: | |
| st.subheader("Product Information") | |
| product_weight = st.number_input("Product Weight", min_value=0.1, max_value=100.0, value=12.5, step=0.1) | |
| product_sugar_content = st.selectbox("Sugar Content", | |
| ["Low Sugar", "Regular", "No Sugar"]) | |
| product_allocated_area = st.slider("Allocated Area Ratio", 0.001, 0.5, 0.05, 0.001) | |
| product_type = st.selectbox("Product Type", | |
| ["Frozen Foods", "Dairy", "Canned", "Baking Goods", "Health and Hygiene", | |
| "Snack Foods", "Meat", "Household", "Soft Drinks", "Hard Drinks", | |
| "Bread", "Breakfast", "Fruits and Vegetables", "Seafood", | |
| "Starchy Foods", "Others"]) | |
| product_mrp = st.number_input("Product MRP", min_value=10.0, max_value=1000.0, value=100.0, step=1.0) | |
| with col2: | |
| st.subheader("Store Information") | |
| store_establishment_year = st.number_input("Store Establishment Year", | |
| min_value=1980, max_value=2024, value=2010) | |
| store_size = st.selectbox("Store Size", ["High", "Medium", "Small"]) | |
| store_location_city_type = st.selectbox("City Type", ["Tier 1", "Tier 2", "Tier 3"]) | |
| store_type = st.selectbox("Store Type", | |
| ["Departmental Store", "Supermarket Type1", | |
| "Supermarket Type2", "Food Mart"]) | |
| # Prediction button | |
| if st.button("Predict Sales", type="primary"): | |
| # Prepare data | |
| input_data = { | |
| "Product_Weight": product_weight, | |
| "Product_Sugar_Content": product_sugar_content, | |
| "Product_Allocated_Area": product_allocated_area, | |
| "Product_Type": product_type, | |
| "Product_MRP": product_mrp, | |
| "Store_Establishment_Year": store_establishment_year, | |
| "Store_Size": store_size, | |
| "Store_Location_City_Type": store_location_city_type, | |
| "Store_Type": store_type | |
| } | |
| # Make prediction | |
| with st.spinner("Making prediction..."): | |
| result = make_prediction(input_data) | |
| if "error" in result: | |
| st.error(f"Error: {result['error']}") | |
| else: | |
| prediction = result["prediction"] | |
| st.markdown(f""" | |
| <div class="prediction-result"> | |
| <h2>Predicted Sales Revenue</h2> | |
| <h1 style="color: #28a745;">₹{prediction:,.2f}</h1> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Additional insights | |
| st.subheader("Insights") | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.metric("Revenue per Unit Weight", f"₹{prediction/product_weight:.2f}") | |
| with col2: | |
| st.metric("Revenue per MRP", f"₹{prediction/product_mrp:.2f}") | |
| with col3: | |
| st.metric("Revenue per Area", f"₹{prediction/product_allocated_area:.2f}") | |
| def batch_prediction_page(): | |
| st.header("Batch Sales Prediction") | |
| st.markdown("Upload a CSV file or enter data manually for batch predictions.") | |
| # File upload option | |
| uploaded_file = st.file_uploader("Upload CSV file", type=['csv']) | |
| if uploaded_file is not None: | |
| try: | |
| df = pd.read_csv(uploaded_file) | |
| st.subheader("Uploaded Data Preview") | |
| st.dataframe(df.head()) | |
| # Validate columns | |
| required_columns = [ | |
| 'Product_Weight', 'Product_Sugar_Content', 'Product_Allocated_Area', | |
| 'Product_Type', 'Product_MRP', 'Store_Establishment_Year', | |
| 'Store_Size', 'Store_Location_City_Type', 'Store_Type' | |
| ] | |
| missing_columns = [col for col in required_columns if col not in df.columns] | |
| if missing_columns: | |
| st.error(f"Missing required columns: {missing_columns}") | |
| else: | |
| if st.button("Predict All", type="primary"): | |
| with st.spinner("Making batch predictions..."): | |
| data_list = df[required_columns].to_dict('records') | |
| result = make_batch_predictions(data_list) | |
| if "error" in result: | |
| st.error(f"Error: {result['error']}") | |
| else: | |
| predictions = result["predictions"] | |
| df['Predicted_Sales'] = predictions | |
| st.subheader("Predictions Results") | |
| st.dataframe(df) | |
| # Download results | |
| csv = df.to_csv(index=False) | |
| st.download_button( | |
| label="Download Results as CSV", | |
| data=csv, | |
| file_name=f"predictions_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", | |
| mime="text/csv" | |
| ) | |
| except Exception as e: | |
| st.error(f"Error reading file: {str(e)}") | |
| # Manual data entry | |
| st.subheader("Manual Data Entry") | |
| st.markdown("Add rows manually for batch prediction") | |
| # Initialize session state for manual data | |
| if 'manual_data' not in st.session_state: | |
| st.session_state.manual_data = [] | |
| # Add new row form | |
| with st.form("add_row_form"): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| weight = st.number_input("Product Weight", min_value=0.1, max_value=100.0, value=12.5, step=0.1, key="weight") | |
| sugar_content = st.selectbox("Sugar Content", ["Low Sugar", "Regular", "No Sugar"], key="sugar") | |
| allocated_area = st.slider("Allocated Area", 0.001, 0.5, 0.05, 0.001, key="area") | |
| product_type = st.selectbox("Product Type", | |
| ["Frozen Foods", "Dairy", "Canned", "Baking Goods", "Health and Hygiene", | |
| "Snack Foods", "Meat", "Household", "Soft Drinks", "Hard Drinks", | |
| "Bread", "Breakfast", "Fruits and Vegetables", "Seafood", | |
| "Starchy Foods", "Others"], key="type") | |
| mrp = st.number_input("Product MRP", min_value=10.0, max_value=1000.0, value=100.0, step=1.0, key="mrp") | |
| with col2: | |
| establishment_year = st.number_input("Store Establishment Year", | |
| min_value=1980, max_value=2024, value=2010, key="year") | |
| size = st.selectbox("Store Size", ["High", "Medium", "Small"], key="size") | |
| city_type = st.selectbox("City Type", ["Tier 1", "Tier 2", "Tier 3"], key="city") | |
| store_type = st.selectbox("Store Type", | |
| ["Departmental Store", "Supermarket Type1", | |
| "Supermarket Type2", "Food Mart"], key="store") | |
| if st.form_submit_button("Add Row"): | |
| new_row = { | |
| 'Product_Weight': weight, | |
| 'Product_Sugar_Content': sugar_content, | |
| 'Product_Allocated_Area': allocated_area, | |
| 'Product_Type': product_type, | |
| 'Product_MRP': mrp, | |
| 'Store_Establishment_Year': establishment_year, | |
| 'Store_Size': size, | |
| 'Store_Location_City_Type': city_type, | |
| 'Store_Type': store_type | |
| } | |
| st.session_state.manual_data.append(new_row) | |
| st.success("Row added successfully!") | |
| # Display manual data | |
| if st.session_state.manual_data: | |
| st.subheader("Manual Data") | |
| manual_df = pd.DataFrame(st.session_state.manual_data) | |
| st.dataframe(manual_df) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.button("Predict Manual Data", type="primary"): | |
| with st.spinner("Making predictions..."): | |
| result = make_batch_predictions(st.session_state.manual_data) | |
| if "error" in result: | |
| st.error(f"Error: {result['error']}") | |
| else: | |
| predictions = result["predictions"] | |
| manual_df['Predicted_Sales'] = predictions | |
| st.subheader("Predictions Results") | |
| st.dataframe(manual_df) | |
| with col2: | |
| if st.button("Clear Data"): | |
| st.session_state.manual_data = [] | |
| st.rerun() | |
| def data_analysis_page(): | |
| st.header("Data Analysis Dashboard") | |
| st.markdown("Explore the SuperKart dataset and model insights.") | |
| # Sample data for analysis (you can load actual data here) | |
| st.subheader("Dataset Overview") | |
| # Create sample data for demonstration | |
| np.random.seed(42) | |
| sample_data = { | |
| 'Product_Type': np.random.choice(['Frozen Foods', 'Dairy', 'Canned', 'Baking Goods'], 100), | |
| 'Store_Size': np.random.choice(['High', 'Medium', 'Small'], 100), | |
| 'Store_Location_City_Type': np.random.choice(['Tier 1', 'Tier 2', 'Tier 3'], 100), | |
| 'Product_MRP': np.random.normal(150, 50, 100), | |
| 'Product_Weight': np.random.normal(15, 5, 100), | |
| 'Predicted_Sales': np.random.normal(3000, 1000, 100) | |
| } | |
| df_sample = pd.DataFrame(sample_data) | |
| # Metrics | |
| col1, col2, col3, col4 = st.columns(4) | |
| with col1: | |
| st.metric("Total Products", len(df_sample)) | |
| with col2: | |
| st.metric("Average Sales", f"₹{df_sample['Predicted_Sales'].mean():,.0f}") | |
| with col3: | |
| st.metric("Max Sales", f"₹{df_sample['Predicted_Sales'].max():,.0f}") | |
| with col4: | |
| st.metric("Min Sales", f"₹{df_sample['Predicted_Sales'].min():,.0f}") | |
| # Charts | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| # Sales by Product Type | |
| fig1 = px.bar(df_sample.groupby('Product_Type')['Predicted_Sales'].mean().reset_index(), | |
| x='Product_Type', y='Predicted_Sales', | |
| title='Average Sales by Product Type') | |
| st.plotly_chart(fig1, use_container_width=True) | |
| with col2: | |
| # Sales by Store Size | |
| fig2 = px.pie(df_sample.groupby('Store_Size')['Predicted_Sales'].sum().reset_index(), | |
| values='Predicted_Sales', names='Store_Size', | |
| title='Sales Distribution by Store Size') | |
| st.plotly_chart(fig2, use_container_width=True) | |
| # Scatter plot | |
| fig3 = px.scatter(df_sample, x='Product_MRP', y='Predicted_Sales', | |
| color='Store_Location_City_Type', | |
| title='Sales vs Product MRP by City Type') | |
| st.plotly_chart(fig3, use_container_width=True) | |
| def about_page(): | |
| st.header("About SuperKart Sales Forecasting") | |
| st.markdown(""" | |
| ## Overview | |
| This application provides sales forecasting for SuperKart retail stores using machine learning models. | |
| ## Features | |
| - **Single Prediction**: Predict sales for individual product-store combinations | |
| - **Batch Prediction**: Process multiple predictions at once | |
| - **Data Analysis**: Explore sales patterns and insights | |
| - **Real-time API**: Fast predictions using deployed ML models | |
| ## Model Information | |
| The forecasting model uses ensemble learning techniques including: | |
| - Random Forest | |
| - XGBoost | |
| - Gradient Boosting | |
| - Decision Trees | |
| ## Data Features | |
| - Product characteristics (weight, sugar content, type, MRP) | |
| - Store information (size, location, type, establishment year) | |
| - Allocated display area | |
| ## API Endpoints | |
| - `POST /predict` - Single prediction | |
| - `POST /batch_predict` - Batch predictions | |
| - `GET /health` - Health check | |
| ## Contact | |
| For questions or support, please contact the development team. | |
| """) | |
| st.subheader("Model Performance") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("R² Score", "0.85+") | |
| st.metric("RMSE", "< 500") | |
| with col2: | |
| st.metric("MAE", "< 300") | |
| st.metric("MAPE", "< 15%") | |
| if __name__ == "__main__": | |
| main() | |