└── Complete Sales Dashboard ├── src ├── pages │ ├── Analysis │ │ ├── Analysis.md │ │ └── Analysis.py │ ├── Overview │ │ ├── Overview.md │ │ └── Overview.py │ ├── root.md │ ├── __init__.py │ ├── root.py │ └── Predictions │ │ ├── Predictions.md │ │ └── Predictions.py ├── requirements.txt ├── data │ ├── supermarkt_sales.xlsx │ └── data_augmentation.py ├── algorithms │ ├── __init__.py │ └── algorithms.py ├── configuration │ ├── __init__.py │ ├── config.toml │ └── config.py └── main.py └── src_single_page_taipy ├── requirements.txt └── main.py /Complete Sales Dashboard/src/pages/Analysis/Analysis.md: -------------------------------------------------------------------------------- 1 | # Analysis 2 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/pages/Overview/Overview.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/requirements.txt: -------------------------------------------------------------------------------- 1 | taipy==3.1.0.dev0 2 | scikit-learn 3 | pmdarima 4 | plotly -------------------------------------------------------------------------------- /Complete Sales Dashboard/src_single_page_taipy/requirements.txt: -------------------------------------------------------------------------------- 1 | taipy==3.1.0.dev0 2 | scikit-learn 3 | pmdarima 4 | plotly -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/data/supermarkt_sales.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmmadHasan/Complete-Sales-Dashboard-Using-Taipy/HEAD/Complete Sales Dashboard/src/data/supermarkt_sales.xlsx -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/pages/root.md: -------------------------------------------------------------------------------- 1 | # Sales **Dashboard**{: .color-primary} 2 | 3 | <|1 1 1|layout| 4 | 7 | |total_sales> 8 | 9 | 12 | |average_rating> 13 | 14 | 17 | |average_sale> 18 | |> 19 | 20 |
21 | <|navbar|> 22 |
23 | 24 | <|Data|expandable|expanded=False| 25 | <|{data}|table|> 26 | |> 27 | 28 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/algorithms/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | from .algorithms import * 13 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/configuration/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | from .config import * 13 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/pages/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | from .root import root_page 13 | from .Overview.Overview import Overview, data 14 | from .Analysis.Analysis import Analysis 15 | from .Predictions.Predictions import Predictions 16 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/pages/root.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | """ 13 | The root page of the application. 14 | Page content is imported from the root.md file. 15 | 16 | Please refer to https://docs.taipy.io/en/latest/manuals/gui/pages for more details. 17 | """ 18 | 19 | from taipy.gui import Markdown 20 | 21 | root_page = Markdown("pages/root.md") 22 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/pages/Predictions/Predictions.md: -------------------------------------------------------------------------------- 1 | <|layout|columns=2 9|gap=50px| 2 | 6 | |sidebar> 7 | 8 | 18 | |date> 19 | 20 | 26 | |country> 27 | |> 28 | 29 | Run your scenario 30 | 31 | <|{selected_scenario}|scenario|on_submission_change=on_submission_change|not expanded|> 32 | 33 | --------------------------------------- 34 | 35 | ## **Predictions**{: .color-primary} and explorer of data nodes 36 | 37 | <|Data Nodes|expandable| 38 | <|1 5|layout| 39 | <|{selected_data_node}|data_node_selector|> 40 | 41 | <|{selected_data_node}|data_node|> 42 | |> 43 | |> 44 | 45 | |scenario> 46 | |> 47 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/main.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | import taipy as tp 12 | from taipy.gui import Gui 13 | 14 | from configuration import scenario_cfg 15 | 16 | from taipy import Core 17 | from pages import * 18 | 19 | 20 | pages = { 21 | "/": root_page, 22 | "Overview": Overview, 23 | "Analysis": Analysis, 24 | "Predictions": Predictions 25 | } 26 | 27 | 28 | if __name__ == "__main__": 29 | core = Core() 30 | core.run() 31 | # ############################################################################# 32 | # PLACEHOLDER: Create and submit your scenario here # 33 | # # 34 | # Example: # 35 | # from configuration import scenario_config # 36 | # scenario = tp.create_scenario(scenario_config) # 37 | # scenario.submit() # 38 | # Comment, remove or replace the previous lines with your own use case # 39 | # ############################################################################# 40 | 41 | gui = Gui(pages=pages) 42 | gui.run(title="Sales", use_reloader=True, port=2452) 43 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/pages/Predictions/Predictions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | """ 13 | A page of the application. 14 | Page content is imported from the Predictions.md file. 15 | 16 | Please refer to https://docs.taipy.io/en/latest/manuals/gui/pages for more details. 17 | """ 18 | 19 | from taipy.gui import Markdown, notify 20 | 21 | 22 | selected_data_node = None 23 | selected_scenario = None 24 | selected_holiday = False 25 | selected_level = 100 26 | 27 | def on_submission_change(state, submitable, details): 28 | if details['submission_status'] == 'COMPLETED': 29 | notify(state, "success", "Predictions ready!") 30 | print("Predictions ready!") 31 | elif details['submission_status'] == 'FAILED': 32 | notify(state, "error", "Submission failed!") 33 | print("Submission failed!") 34 | else: 35 | notify(state, "info", "In progress...") 36 | print("In progress...") 37 | 38 | 39 | def on_change_params(state): 40 | state.selected_scenario.level.write(state.selected_level/100) 41 | state.selected_scenario.holiday.write(state.selected_holiday) 42 | notify(state, "success", "Scenario parameters changed!") 43 | 44 | def on_change(state, var_name, var_value): 45 | if var_name == 'selected_scenario' and var_value: 46 | state.selected_level = state.selected_scenario.level.read()*100 47 | state.selected_holiday = state.selected_scenario.holiday.read() 48 | 49 | Predictions = Markdown("pages/Predictions/Predictions.md") -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/configuration/config.toml: -------------------------------------------------------------------------------- 1 | [TAIPY] 2 | 3 | [DATA_NODE.initial_data] 4 | storage_type = "csv" 5 | scope = "GLOBAL:SCOPE" 6 | path = "data/modified_supermarkt_sales_plus.csv" 7 | 8 | [DATA_NODE.holiday] 9 | default_data = "False:bool" 10 | 11 | [DATA_NODE.level] 12 | default_data = "1:int" 13 | 14 | [DATA_NODE.date] 15 | 16 | [DATA_NODE.final_data] 17 | 18 | [DATA_NODE.model_arima] 19 | 20 | [DATA_NODE.model_xgboost] 21 | 22 | [DATA_NODE.predictions_arima] 23 | 24 | [DATA_NODE.predictions_xgboost] 25 | 26 | [DATA_NODE.result] 27 | 28 | [TASK.task_preprocess_data] 29 | function = "algorithms.algorithms.preprocess:function" 30 | inputs = [ "initial_data:SECTION", "holiday:SECTION", "level:SECTION",] 31 | outputs = [ "final_data:SECTION", "date:SECTION",] 32 | skippable = "False:bool" 33 | 34 | [TASK.task_train] 35 | function = "algorithms.algorithms.train_arima:function" 36 | inputs = [ "final_data:SECTION",] 37 | outputs = [ "model_arima:SECTION",] 38 | skippable = "False:bool" 39 | 40 | [TASK.task_forecast] 41 | function = "algorithms.algorithms.forecast:function" 42 | inputs = [ "model_arima:SECTION",] 43 | outputs = [ "predictions_arima:SECTION",] 44 | skippable = "False:bool" 45 | 46 | [TASK.task_train_xgboost] 47 | function = "algorithms.algorithms.train_xgboost:function" 48 | inputs = [ "final_data:SECTION",] 49 | outputs = [ "model_xgboost:SECTION",] 50 | skippable = "False:bool" 51 | 52 | [TASK.task_forecast_xgboost] 53 | function = "algorithms.algorithms.forecast_xgboost:function" 54 | inputs = [ "model_xgboost:SECTION", "date:SECTION",] 55 | outputs = [ "predictions_xgboost:SECTION",] 56 | skippable = "False:bool" 57 | 58 | [TASK.task_result] 59 | function = "algorithms.algorithms.concat:function" 60 | inputs = [ "final_data:SECTION", "predictions_arima:SECTION", "predictions_xgboost:SECTION",] 61 | outputs = [ "result:SECTION",] 62 | skippable = "False:bool" 63 | 64 | [SCENARIO.scenario] 65 | tasks = [ "task_preprocess_data:SECTION", "task_train:SECTION", "task_forecast:SECTION", "task_train_xgboost:SECTION", "task_forecast_xgboost:SECTION", "task_result:SECTION",] 66 | additional_data_nodes = [] 67 | 68 | [SCENARIO.scenario.comparators] 69 | 70 | [SCENARIO.scenario.sequences] 71 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/pages/Overview/Overview.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import plotly.express as px 3 | import taipy.gui.builder as tgb 4 | 5 | # Load the dataset 6 | data = pd.read_csv('data/modified_supermarkt_sales_plus.csv') 7 | 8 | def create_pie_figure(data, group_by): 9 | grouped_data = data.groupby(group_by)['Total'].sum().reset_index() 10 | grouped_data['Total'] = grouped_data['Total'].round(2) 11 | fig = px.pie(grouped_data, names=group_by, values='Total', title=f"Sales Performance by {group_by}", hole=0.3) 12 | return fig 13 | 14 | def create_bar_figure(data, group_by): 15 | sales_over_time = data.groupby(group_by)['Total'].sum().reset_index() 16 | fig = px.bar(sales_over_time, x=group_by, y='Total', title='Sales Trends Over Time', color='Total') 17 | return fig 18 | 19 | import os 20 | 21 | def create_sales_by_city_map(data): 22 | mapbox_access_token = os.environ.get('MAPBOX_ACCESS_TOKEN') 23 | px.set_mapbox_access_token(mapbox_access_token) 24 | city_sales = data.groupby('City').agg({'Total': 'sum', 'Latitude': 'mean', 'Longitude': 'mean'}).reset_index() 25 | fig = px.scatter_mapbox(city_sales, lat="Latitude", lon="Longitude", size="Total", color="Total", text="City", 26 | zoom=5, center={"lat": 18.7, "lon": 98.9}, mapbox_style="dark", title='Total Sales by City', size_max=50) 27 | fig.update_layout(title={'text': "Total Sales by City", 'y': 0.9, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top'}, 28 | legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01), 29 | margin={"r": 0, "t": 0, "l": 0, "b": 0}) 30 | return fig 31 | 32 | fig_product_line = create_pie_figure(data, 'Product_line') 33 | fig_city = create_pie_figure(data, 'City') 34 | fig_customer_type = create_pie_figure(data, 'Customer_type') 35 | 36 | with tgb.Page() as Overview: 37 | # Sales by City Map 38 | tgb.chart(figure="{create_sales_by_city_map(data)}", height="600px") 39 | 40 | with tgb.layout(columns="1 1 1"): 41 | tgb.chart(figure="{fig_product_line}") 42 | tgb.chart(figure="{fig_city}") 43 | tgb.chart(figure="{fig_customer_type}") 44 | 45 | tgb.chart(figure="{create_bar_figure(data, 'Time')}") 46 | 47 | tgb.chart(figure="{create_bar_figure(data, 'Date')}") -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/data/data_augmentation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import string 4 | import random 5 | 6 | 7 | # Seed for reproducibility 8 | np.random.seed(42) 9 | 10 | data = pd.read_csv('data/supermarkt_sales_clean.csv') 11 | 12 | def generate_invoice_id(n): 13 | """Generate n unique Invoice IDs in the format 'XXX-XX-XXXX'.""" 14 | invoice_ids = set() 15 | while len(invoice_ids) < n: 16 | # Generate parts of the Invoice ID 17 | part1 = ''.join(random.choices(string.ascii_uppercase, k=3)) 18 | part2 = ''.join(random.choices(string.digits, k=2)) 19 | part3 = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4)) 20 | 21 | # Combine parts into one ID 22 | invoice_id = f"{part1}-{part2}-{part3}" 23 | 24 | # Add to the set of Invoice IDs 25 | invoice_ids.add(invoice_id) 26 | 27 | return list(invoice_ids) 28 | 29 | num_entries = 5_000 30 | new_branches = np.random.choice(['A', 'B', 'C', 'D', 'E', 'F'], size=num_entries) 31 | new_invoice = generate_invoice_id(num_entries) 32 | new_products = np.random.choice(list(data['Product line'].unique()), size=num_entries) 33 | new_customer_types = np.random.choice(['Member', 'Normal'], size=num_entries) 34 | new_genders = np.random.choice(['Male', 'Female'], size=num_entries) 35 | new_unit_prices = np.random.uniform(10, 100, size=num_entries) 36 | new_quantities = np.random.randint(1, 10, size=num_entries) 37 | new_tax = new_unit_prices * new_quantities * 0.05 38 | new_totals = new_unit_prices * new_quantities + new_tax 39 | new_cogs = new_unit_prices * new_quantities 40 | new_gross_margin_percentage = np.full(shape=num_entries, fill_value=4.761905) 41 | new_gross_income = new_tax 42 | new_ratings = np.random.uniform(1, 10, size=num_entries) 43 | new_dates = np.random.choice(pd.date_range(start='2021-01-01', end='2021-12-31'), size=num_entries) 44 | new_times = [f"{np.random.randint(10, 19)}:{np.random.randint(0, 59):02d}:00" for _ in range(num_entries)] 45 | new_payments = np.random.choice(['Cash', 'Ewallet', 'Credit card'], size=num_entries) 46 | 47 | 48 | cities_latitudes = { 49 | 'Bangkok': (13.736717, 100.523186), 50 | 'Chiang Mai': (18.796143, 98.979263), 51 | 'Vientiane': (17.974855, 102.630867), 52 | 'Luang Prabang': (19.889271, 102.133453), 53 | } 54 | 55 | # Select a city for each new entry and retrieve its latitude 56 | new_cities = np.random.choice(list(cities_latitudes.keys()), size=num_entries) 57 | new_latitudes = np.array([cities_latitudes[city][0] for city in new_cities]) 58 | new_longitudes = np.array([cities_latitudes[city][1] for city in new_cities]) 59 | 60 | # Create DataFrame for additional data 61 | additional_data = pd.DataFrame({ 62 | 'Invoice ID': new_invoice, 63 | 'Branch': new_branches, 64 | 'City': new_cities, 65 | 'Customer_type': new_customer_types, 66 | 'Gender': new_genders, 67 | 'Product_line': new_products, 68 | 'Unit price': new_unit_prices, 69 | 'Quantity': new_quantities, 70 | 'Tax 5%': new_tax, 71 | 'Total': new_totals, 72 | 'Date': new_dates, 73 | 'Time': new_times, 74 | 'Payment': new_payments, 75 | 'cogs': new_cogs, 76 | 'gross_margin_percentage': new_gross_margin_percentage, 77 | 'gross_income': new_gross_income, 78 | 'Rating': new_ratings, 79 | 'Latitude': new_latitudes, 80 | 'Longitude': new_longitudes 81 | }) 82 | 83 | # Concatenate the additional data with the existing dataset 84 | augmented_data = pd.concat([data, additional_data]).reset_index(drop=True) 85 | 86 | 87 | augmented_data.to_csv('data/modified_supermarkt_sales_plus.csv') -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/pages/Analysis/Analysis.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | """ 13 | A page of the application. 14 | Page content is imported from the Analysis.md file. 15 | 16 | Please refer to https://docs.taipy.io/en/latest/manuals/gui/pages for more details. 17 | """ 18 | from taipy.gui import Markdown 19 | import pandas as pd 20 | import plotly.express as px 21 | import taipy.gui.builder as tgb 22 | 23 | # Assuming data is loaded from 'data/modified_supermarkt_sales_plus.csv' 24 | data = pd.read_csv('data/modified_supermarkt_sales_plus.csv') 25 | 26 | data['Date'] = pd.to_datetime(data['Date']) 27 | data['Month_Year'] = data['Date'].dt.to_period('M').dt.to_timestamp() 28 | 29 | 30 | def create_perc_fig(df, group_column): 31 | # Group, sum, and convert to percentage 32 | df = df.groupby(['Month_Year', group_column])['Total'].sum().unstack(fill_value=0) 33 | df = df.div(df.sum(axis=1), axis=0).reset_index().melt(id_vars='Month_Year', var_name=group_column, value_name='Percentage') 34 | df['Percentage'] = (df.loc[:, 'Percentage'].round(3) * 100) 35 | 36 | # Create and return the plot 37 | fig = px.bar(df, x='Month_Year', y='Percentage', color=group_column, title=f"Evolution of Sales by {group_column} over Time", labels={'Percentage': '% of Total'}, text_auto=True) 38 | return fig 39 | 40 | fig_product_line = create_perc_fig(data, 'Product_line') 41 | fig_city = create_perc_fig(data, 'City') 42 | fig_gender = create_perc_fig(data, 'Gender') 43 | fig_customer_type = create_perc_fig(data, 'Customer_type') 44 | 45 | import time 46 | 47 | def on_change(state, var_name, var_value): 48 | if var_name in ['city', 'customer_type', 'gender']: 49 | data = state.data.loc[ 50 | state.data["City"].isin(state.city) 51 | & state.data["Customer_type"].isin(state.customer_type) 52 | & state.data["Gender"].isin(state.gender), : 53 | ] 54 | 55 | state.fig_product_line = create_perc_fig(data, 'Product_line') 56 | state.fig_city = create_perc_fig(data, 'City') 57 | state.fig_gender = create_perc_fig(data, 'Gender') 58 | state.fig_customer_type = create_perc_fig(data, 'Customer_type') 59 | 60 | 61 | customer_type = ["Normal", "Member"] 62 | gender = ["Male", "Female"] 63 | city = ["Bangkok", "Chiang Mai", "Vientiane", "Luang Prabang"] 64 | 65 | with tgb.Page() as Analysis: 66 | with tgb.layout(columns="1 1 1"): 67 | tgb.selector(value="{customer_type}", lov=customer_type, multiple=True, dropdown=True, class_name="fullwidth", label="Customer Type") 68 | tgb.selector(value="{gender}", lov=gender, multiple=True, dropdown=True, class_name="fullwidth", label="Gender") 69 | tgb.selector(value="{city}", lov=city, multiple=True, dropdown=True, class_name="fullwidth", label="City") 70 | 71 | 72 | with tgb.layout(columns="1 1"): 73 | tgb.chart(figure="{fig_customer_type}") 74 | tgb.chart(figure="{fig_city}") 75 | tgb.chart(figure="{fig_gender}") 76 | tgb.chart(figure="{fig_product_line}") 77 | 78 | 79 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/algorithms/algorithms.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | """ 13 | This file is designed to contain the various Python functions used to configure tasks. 14 | 15 | The functions will be imported by the __init__.py file in this folder. 16 | """ 17 | 18 | import pandas as pd 19 | from sklearn.ensemble import GradientBoostingRegressor 20 | import datetime as dt 21 | import numpy as np 22 | from pmdarima import auto_arima 23 | 24 | 25 | def add_features(data): 26 | dates = pd.to_datetime(data["Date"]) 27 | data["Months"] = (dates.dt.month - 6)/12 28 | data["Days"] = (dates.dt.isocalendar().day - 15)/30 29 | data["Week"] = (dates.dt.isocalendar().week - 26)/52 30 | data["Day of week"] = (dates.dt.dayofweek - 3.5)/7 31 | # Number of days after 30 December 2020 32 | data["Index"] = (dates - dt.datetime(2020, 12, 30)).dt.days 33 | return data 34 | 35 | def preprocess(initial_data, holiday, level): 36 | data = initial_data.groupby(['Date'])\ 37 | .sum()\ 38 | .dropna()\ 39 | .reset_index() 40 | 41 | data['Date'] = pd.to_datetime(data['Date']) 42 | final_data = data[['Date','Total']] 43 | final_data = add_features(final_data) 44 | 45 | final_data['Total'] = final_data['Total']*level 46 | if holiday: 47 | final_data['Total'] *= 0.8 48 | 49 | date = final_data['Date'].max() 50 | return final_data, date 51 | 52 | def train_arima(train_data): 53 | model = auto_arima(train_data['Total'], 54 | start_p=1, start_q=1, 55 | max_p=5, max_q=5, 56 | start_P=0, seasonal=False, 57 | d=1, D=1, trace=True, 58 | error_action='ignore', 59 | suppress_warnings=True) 60 | model.fit(train_data['Total']) 61 | return model 62 | 63 | def forecast(model): 64 | predictions = model.predict(n_periods=60) 65 | return np.array(predictions) 66 | 67 | def train_xgboost(train_data): 68 | y = train_data['Total'] 69 | X = train_data.drop(['Total','Date'], axis=1) 70 | 71 | model = GradientBoostingRegressor() 72 | model.fit(X,y) 73 | return model 74 | 75 | def forecast_xgboost(model, date): 76 | dates = pd.to_datetime([date + dt.timedelta(days=i) 77 | for i in range(60)]) 78 | X = add_features(pd.DataFrame({"Date":dates})) 79 | X.drop('Date', axis=1, inplace=True) 80 | predictions = model.predict(X) 81 | return predictions 82 | 83 | 84 | def concat(final_data, predictions_arima, predictions_xgboost): 85 | date = final_data['Date'].max() 86 | 87 | def _convert_predictions(final_data, predictions, date, label='Predictions'): 88 | dates = pd.to_datetime([date + dt.timedelta(days=i) 89 | for i in range(len(predictions))]) 90 | final_data['Date'] = pd.to_datetime(final_data['Date']) 91 | final_data = final_data[['Date','Total']] 92 | predictions = pd.concat([pd.Series(dates, name="Date"), 93 | pd.Series(predictions, name=label)], axis=1) 94 | return final_data.merge(predictions, on="Date", how="outer") 95 | 96 | result_arima = _convert_predictions(final_data, predictions_arima, date, label='ARIMA') 97 | result_xgboost = _convert_predictions(final_data, predictions_xgboost, date, label='Xgboost') 98 | return result_arima.merge(result_xgboost, on=["Date", 'Total'], how="outer").sort_values(by='Date') 99 | -------------------------------------------------------------------------------- /Complete Sales Dashboard/src/configuration/config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Avaiga Private Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 4 | # the License. You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 9 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | 12 | """ 13 | Contain the application's configuration including the scenario configurations. 14 | 15 | The configuration is run by the Core service. 16 | """ 17 | 18 | from algorithms import * 19 | 20 | from taipy import Config 21 | 22 | from taipy.config import Config, Scope 23 | import datetime as dt 24 | 25 | 26 | #Config.configure_job_executions(mode="standalone", nb_of_workers=2) 27 | 28 | path_to_data = "data/modified_supermarkt_sales_plus.csv" 29 | 30 | initial_data_cfg = Config.configure_data_node(id="initial_data", 31 | storage_type="csv", 32 | path=path_to_data, 33 | scope=Scope.GLOBAL) 34 | 35 | holiday_cfg = Config.configure_data_node(id="holiday", default_data=False) 36 | level_cfg = Config.configure_data_node(id="level", default_data=1) 37 | date_cfg = Config.configure_data_node(id="date") 38 | 39 | final_data_cfg = Config.configure_data_node(id="final_data") 40 | 41 | 42 | model_arima_cfg = Config.configure_data_node(id="model_arima") 43 | model_xgboost_cfg = Config.configure_data_node(id="model_xgboost") 44 | 45 | predictions_arima_cfg = Config.configure_data_node(id="predictions_arima") 46 | predictions_xgboost_cfg = Config.configure_data_node(id="predictions_xgboost") 47 | 48 | result_cfg = Config.configure_data_node(id="result") 49 | 50 | 51 | task_preprocess_cfg = Config.configure_task(id="task_preprocess_data", 52 | function=preprocess, 53 | input=[initial_data_cfg, holiday_cfg, level_cfg], 54 | output=[final_data_cfg, date_cfg]) 55 | 56 | 57 | task_train_arima_cfg = Config.configure_task(id="task_train", 58 | function=train_arima, 59 | input=final_data_cfg, 60 | output=model_arima_cfg) 61 | 62 | task_forecast_arima_cfg = Config.configure_task(id="task_forecast", 63 | function=forecast, 64 | input=model_arima_cfg, 65 | output=predictions_arima_cfg) 66 | 67 | 68 | task_train_xgboost_cfg = Config.configure_task(id="task_train_xgboost", 69 | function=train_xgboost, 70 | input=final_data_cfg, 71 | output=model_xgboost_cfg) 72 | 73 | task_forecast_xgboost_cfg = Config.configure_task(id="task_forecast_xgboost", 74 | function=forecast_xgboost, 75 | input=[model_xgboost_cfg, date_cfg], 76 | output=predictions_xgboost_cfg) 77 | 78 | task_result_cfg = Config.configure_task(id="task_result", 79 | function=concat, 80 | input=[final_data_cfg, 81 | predictions_arima_cfg, 82 | predictions_xgboost_cfg], 83 | output=result_cfg) 84 | 85 | 86 | scenario_cfg = Config.configure_scenario(id='scenario', task_configs=[task_preprocess_cfg, 87 | task_train_arima_cfg, 88 | task_forecast_arima_cfg, 89 | task_train_xgboost_cfg, 90 | task_forecast_xgboost_cfg, 91 | task_result_cfg]) 92 | 93 | Config.export('configuration/config.toml') -------------------------------------------------------------------------------- /Complete Sales Dashboard/src_single_page_taipy/main.py: -------------------------------------------------------------------------------- 1 | from taipy.gui import Gui 2 | import pandas as pd 3 | import plotly.express as px 4 | import taipy.gui.builder as tgb 5 | 6 | 7 | data = pd.read_csv('data/modified_supermarkt_sales_plus.csv') 8 | 9 | 10 | def create_pie_figure(data, group_by: str): 11 | grouped_data = data.groupby(group_by)['Total'].sum().reset_index() 12 | grouped_data['Total'] = grouped_data['Total'].round(2) 13 | fig = px.pie(grouped_data, names=group_by, values='Total', title=f"Sales Performance by {group_by}", hole=0.3) 14 | return fig 15 | 16 | def create_bar_figure(data, group_by: str): 17 | sales_over_time = data.groupby(group_by)['Total'].sum().reset_index() 18 | fig = px.bar(sales_over_time, x=group_by, y='Total', title='Sales Trends Over Time', color='Total') 19 | return fig 20 | 21 | def create_sales_by_city_map(data): 22 | # mapbox_access_token = ... 23 | # px.set_mapbox_access_token(mapbox_access_token) 24 | city_sales = data.groupby('City').agg({'Total': 'sum', 'Latitude': 'mean', 'Longitude': 'mean'}).reset_index() 25 | fig = px.scatter_mapbox(city_sales, lat="Latitude", lon="Longitude", size="Total", color="Total", text="City", 26 | zoom=5, center={"lat": 18.7, "lon": 98.9}, mapbox_style="dark", title='Total Sales by City', size_max=50) 27 | fig.update_layout(title={'text': "Total Sales by City", 'y': 0.9, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top'}, 28 | legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01), 29 | margin={"r": 0, "t": 0, "l": 0, "b": 0}) 30 | return fig 31 | 32 | 33 | def create_perc_fig(df, group_column): 34 | # Group, sum, and convert to percentage 35 | df = df.groupby(['Month_Year', group_column])['Total'].sum().unstack(fill_value=0) 36 | df = df.div(df.sum(axis=1), axis=0).reset_index().melt(id_vars='Month_Year', var_name=group_column, value_name='Percentage') 37 | df['Percentage'] = (df.loc[:, 'Percentage'].round(3) * 100) 38 | 39 | # Create and return the plot 40 | fig = px.bar(df, x='Month_Year', y='Percentage', color=group_column, title=f"Evolution of Sales by {group_column} over Time", labels={'Percentage': '% of Total'}, text_auto=True) 41 | return fig 42 | 43 | 44 | fig_map = create_sales_by_city_map(data) 45 | 46 | fig_product_line = create_pie_figure(data, 'Product_line') 47 | fig_city = create_pie_figure(data, 'City') 48 | fig_customer_type = create_pie_figure(data, 'Customer_type') 49 | 50 | fig_time = create_bar_figure(data, 'Time') 51 | fig_date = create_bar_figure(data, 'Date') 52 | 53 | 54 | 55 | 56 | city = ["Bangkok", "Chiang Mai", "Vientiane", "Luang Prabang", "Yangon", "Naypyitaw"] 57 | 58 | filtered_data = data.loc[ 59 | data["City"].isin(city) 60 | ] 61 | 62 | fig_product_line_perc = create_perc_fig(filtered_data, 'Product_line') 63 | fig_city_perc = create_perc_fig(filtered_data, 'City') 64 | fig_gender_perc = create_perc_fig(filtered_data, 'Gender') 65 | fig_customer_type_perc = create_perc_fig(filtered_data, 'Customer_type') 66 | 67 | 68 | def on_selector(state): 69 | filtered_data = state.data.loc[ 70 | state.data["City"].isin(state.city) 71 | ] 72 | 73 | state.fig_product_line_perc = create_perc_fig(filtered_data, 'Product_line') 74 | state.fig_city_perc = create_perc_fig(filtered_data, 'City') 75 | state.fig_gender_perc = create_perc_fig(filtered_data, 'Gender') 76 | state.fig_customer_type_perc = create_perc_fig(filtered_data, 'Customer_type') 77 | 78 | 79 | 80 | 81 | with tgb.Page() as page: 82 | tgb.text("Sales Insights", class_name="h1") 83 | 84 | with tgb.layout("1 1 1"): 85 | with tgb.part(): 86 | tgb.text("Total Sales", class_name="h2") 87 | tgb.text("{int(data['Total'].sum())}", class_name="h3") 88 | 89 | with tgb.part(): 90 | tgb.text("Average Sales", class_name="h2") 91 | tgb.text("{int(data['Total'].mean())}", class_name="h3") 92 | 93 | with tgb.part(): 94 | tgb.text("Mean Rating", class_name="h2") 95 | tgb.text("{int(data['Rating'].mean())}", class_name="h3") 96 | 97 | tgb.chart(figure="{fig_map}") 98 | 99 | with tgb.layout("1 1 1"): 100 | tgb.chart(figure="{fig_product_line}") 101 | tgb.chart(figure="{fig_city}") 102 | tgb.chart(figure="{fig_customer_type}") 103 | 104 | tgb.chart(figure="{fig_time}") 105 | tgb.chart(figure="{fig_date}") 106 | 107 | tgb.text("Analysis", class_name="h2") 108 | 109 | tgb.selector(value="{city}", lov=["Bangkok", "Chiang Mai", "Vientiane", "Luang Prabang", "Yangon", "Naypyitaw"], 110 | dropdown=True, 111 | multiple=True, 112 | label="Select cities", 113 | class_name="fullwidth", 114 | on_change=on_selector) 115 | 116 | with tgb.layout("1 1"): 117 | tgb.chart(figure="{fig_product_line_perc}") 118 | tgb.chart(figure="{fig_city_perc}") 119 | tgb.chart(figure="{fig_gender_perc}") 120 | tgb.chart(figure="{fig_customer_type_perc}") 121 | 122 | tgb.table("{data}") 123 | 124 | 125 | if __name__ == "__main__": 126 | gui = Gui(page) 127 | gui.run(title="Sales", port=2452) 128 | --------------------------------------------------------------------------------