File size: 15,240 Bytes
123e8bd
8d8a546
123e8bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97d15ff
123e8bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8d8a546
123e8bd
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

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()