diff --git "a/pages/2_Scenario_Planner.py" "b/pages/2_Scenario_Planner.py" --- "a/pages/2_Scenario_Planner.py" +++ "b/pages/2_Scenario_Planner.py" @@ -10,7 +10,8 @@ from dateutil.relativedelta import relativedelta import time import Streamlit_functions as sf from utilities import ( - format_numbers,format_numbers_f, + format_numbers, + format_numbers_f, load_local_css, set_header, initialize_data, @@ -19,13 +20,15 @@ from utilities import ( channel_name_formating, ) from io import BytesIO + # import xlsxwriter import warnings + # Suppress specific warnings if necessary -warnings.filterwarnings("ignore") +warnings.filterwarnings("ignore") warnings.filterwarnings("ignore", category=UserWarning, message="The widget with key") # for i in : - # warnings.filterwarnings("ignore",) +# warnings.filterwarnings("ignore",) from classes import class_from_dict, class_to_dict import pickle import streamlit_authenticator as stauth @@ -53,111 +56,135 @@ for k, v in st.session_state.items(): # ======================= Functions ====================== # # ======================================================== # -def save_report_forecast(forecasted_table_df,forecasted_table_df2): + +def save_report_forecast(forecasted_table_df, forecasted_table_df2): # Convert the DataFrame to an Excel file in memory excel_file = BytesIO() - with pd.ExcelWriter(excel_file, engine='openpyxl') as writer: - forecasted_table_df.to_excel(writer, index=True, sheet_name='Forecasted Spends') - forecasted_table_df2.to_excel(writer, sheet_name='Monthly Breakdown',index = True) + with pd.ExcelWriter(excel_file, engine="openpyxl") as writer: + forecasted_table_df.to_excel(writer, index=True, sheet_name="Forecasted Spends") + forecasted_table_df2.to_excel( + writer, sheet_name="Monthly Breakdown", index=True + ) # Seek to the beginning of the BytesIO buffer excel_file.seek(0) return excel_file - -def save_ppt_file(summary_df_sorted,fig1,fig2,fig3): + + +def save_ppt_file(summary_df_sorted, fig1, fig2, fig3): summary_df_sorted.index = summary_df_sorted["Channel_name"] # Initialize PowerPoint presentation prs = Presentation() + # Helper function to add Plotly figure to slide def add_plotly_chart_to_slide(slide, fig, left, top, width, height): img_stream = BytesIO() - pio.write_image(fig, img_stream, format='png') + pio.write_image(fig, img_stream, format="png") slide.shapes.add_picture(img_stream, left, top, width, height) - for i in range(0,len(channels_list)): + for i in range(0, len(channels_list)): # # print(channels_list[i]) slide_1 = prs.slides.add_slide(prs.slide_layouts[6]) - fig = rc.response_curves(channels_list[i], summary_df_sorted["Optimized_spend"][channels_list[i]], summary_df_sorted["New_sales"][channels_list[i]]) - add_plotly_chart_to_slide(slide_1, fig, Inches(0.1), Inches(0.1), width=Inches(9), height=Inches(7)) + fig = rc.response_curves( + channels_list[i], + summary_df_sorted["Optimized_spend"][channels_list[i]], + summary_df_sorted["New_sales"][channels_list[i]], + ) + add_plotly_chart_to_slide( + slide_1, fig, Inches(0.1), Inches(0.1), width=Inches(9), height=Inches(7) + ) # Update layout fig1.update_layout( legend=dict( orientation="h", # Horizontal orientation - yanchor="top", # Anchor the legend at the top - y=-0.4, # Position the legend below the plot area - xanchor="center", # Center the legend horizontally - x=0.5 # Center the legend on the x-axis + yanchor="top", # Anchor the legend at the top + y=-0.4, # Position the legend below the plot area + xanchor="center", # Center the legend horizontally + x=0.5, # Center the legend on the x-axis ) ) # Update layout fig2.update_layout( - legend=dict( + legend=dict( orientation="h", # Horizontal orientation - yanchor="top", # Anchor the legend at the top - y=-0.4, # Position the legend below the plot area - xanchor="center", # Center the legend horizontally - x=0.5 # Center the legend on the x-axis + yanchor="top", # Anchor the legend at the top + y=-0.4, # Position the legend below the plot area + xanchor="center", # Center the legend horizontally + x=0.5, # Center the legend on the x-axis ) ) # Update layout fig3.update_layout( legend=dict( orientation="h", # Horizontal orientation - yanchor="top", # Anchor the legend at the top - y=-0.4, # Position the legend below the plot area - xanchor="center", # Center the legend horizontally - x=0.5 # Center the legend on the x-axis + yanchor="top", # Anchor the legend at the top + y=-0.4, # Position the legend below the plot area + xanchor="center", # Center the legend horizontally + x=0.5, # Center the legend on the x-axis ) ) - - slide_1 = prs.slides.add_slide(prs.slide_layouts[6]) - add_plotly_chart_to_slide(slide_1, fig1, Inches(0.1), Inches(1), width=Inches(9.5), height=Inches(6)) + add_plotly_chart_to_slide( + slide_1, fig1, Inches(0.1), Inches(1), width=Inches(9.5), height=Inches(6) + ) slide_1 = prs.slides.add_slide(prs.slide_layouts[6]) - add_plotly_chart_to_slide(slide_1, fig2, Inches(0.1), Inches(1), width=Inches(9.5), height=Inches(6)) + add_plotly_chart_to_slide( + slide_1, fig2, Inches(0.1), Inches(1), width=Inches(9.5), height=Inches(6) + ) slide_1 = prs.slides.add_slide(prs.slide_layouts[6]) - add_plotly_chart_to_slide(slide_1, fig3, Inches(0.1), Inches(1), width=Inches(9.5), height=Inches(6)) - - + add_plotly_chart_to_slide( + slide_1, fig3, Inches(0.1), Inches(1), width=Inches(9.5), height=Inches(6) + ) # Save to a BytesIO object ppt_stream = BytesIO() prs.save(ppt_stream) ppt_stream.seek(0) - + return ppt_stream.getvalue() + def first_day_of_next_year(date): next_year = date.year + 1 first_day = datetime(next_year, 1, 1).date() - + # Calculate the last day of the next year - last_day = (first_day + relativedelta(years=1, days=-1)) - + last_day = first_day + relativedelta(years=1, days=-1) + return first_day, last_day + def first_day_of_next_quarter(date): current_quarter = (date.month - 1) // 3 + 1 next_quarter_first_month = ((current_quarter % 4) * 3) + 1 next_quarter_year = date.year if next_quarter_first_month > 1 else date.year + 1 # Ensure month is within valid range if next_quarter_first_month < 1 or next_quarter_first_month > 12: - raise ValueError("Calculated month is out of range: {}".format(next_quarter_first_month)) + raise ValueError( + "Calculated month is out of range: {}".format(next_quarter_first_month) + ) # st.write(next_quarter_first_month) - first_day_next_quarter = datetime(next_quarter_year, next_quarter_first_month, 1).date() - last_day_next_quarter = (first_day_next_quarter + relativedelta(months=3)) - relativedelta(days=1) - + first_day_next_quarter = datetime( + next_quarter_year, next_quarter_first_month, 1 + ).date() + last_day_next_quarter = ( + first_day_next_quarter + relativedelta(months=3) + ) - relativedelta(days=1) + return first_day_next_quarter, last_day_next_quarter def first_day_of_next_month(date): next_month_date = date + relativedelta(months=1) first_day_next_month = next_month_date.replace(day=1) - last_day_next_month = (first_day_next_month + relativedelta(months=1)) - relativedelta(days=1) + last_day_next_month = ( + first_day_next_month + relativedelta(months=1) + ) - relativedelta(days=1) return first_day_next_month, last_day_next_month + def optimize(key, status_placeholder): """ Optimize the spends for the sales @@ -175,15 +202,14 @@ def optimize(key, status_placeholder): # # # # print(channel_list) # # # # print(st.session_state["total_spends_change"]) result = st.session_state["scenario"].optimize( - st.session_state["total_spends_change"], channel_list + st.session_state["total_spends_change"], + channel_list, # result = st.session_state["scenario"].spends_optimisation( # st.session_state["total_spends_change"], channel_list ) # # print("") # # print(list(zip(*result))) - - # elif key.lower() == "revenue": else: with status_placeholder: @@ -223,6 +249,7 @@ def save_scenario(scenario_name): st.session_state["scenario"] ) st.session_state["scenario_input"] = "" + # # # # print(type(st.session_state['saved_scenarios'])) with open("../saved_scenarios.pkl", "wb") as f: pickle.dump(st.session_state["saved_scenarios"], f) @@ -262,11 +289,11 @@ def update_sales_abs(): # and st.session_state["allow_sales_update"] # ): modified_sales = extract_number_for_string( - st.session_state["total_sales_change_abs"] - ) + st.session_state["total_sales_change_abs"] + ) st.session_state["total_sales_change"] = round( - ((modified_sales / actual_sales) - 1) * 100 - ) + ((modified_sales / actual_sales) - 1) * 100 + ) st.session_state["total_sales_change_abs_slider"] = numerize(modified_sales, 1) @@ -397,42 +424,54 @@ def validate_input(string_input): return False return True + def validate_input_lb(string_input): pattern = r"\d+\.?\d*[K|M|B]$" match = re.match(pattern, string_input) if match is None: return False - response_curve_params = pd.read_excel("response_curves_parameters.xlsx",index_col = "channel") - param_dicts = {col: response_curve_params[col].to_dict() for col in response_curve_params.columns} - if float(string_input) < round(param_dicts["x_min"][channel_name]*10400/param_dicts["current_spends"][channel_name]): + response_curve_params = pd.read_excel( + "response_curves_parameters.xlsx", index_col="channel" + ) + param_dicts = { + col: response_curve_params[col].to_dict() + for col in response_curve_params.columns + } + if float(string_input) < round( + param_dicts["x_min"][channel_name] + * 10400 + / param_dicts["current_spends"][channel_name] + ): return False return True + def update_data_bound_min(channel_name): """ Updates the bounds for the given channel """ if validate_input_lb(st.session_state[f"{channel_name}_lower_bound"]): modified_bounds = st.session_state[f"{channel_name}_lower_bound"] - + # st.session_state['scenario']['channels'][channel_name].channel_bounds_min = st.session_state[f"{channel_name}_lower_bound"] - st.session_state['scenario'].update_bounds_min(channel_name,modified_bounds) + st.session_state["scenario"].update_bounds_min(channel_name, modified_bounds) st.write(st.session_state["scenario"].channels[channel_name].channel_bounds_min) # st.write(st.session_state["scenario"].channels[channel_name] - + def update_data_bound_max(channel_name): """ Updates the bounds for the given channel """ modified_bounds = st.session_state[f"{channel_name}_upper_bound"] - + # st.session_state['scenario']['channels'][channel_name].channel_bounds_min = st.session_state[f"{channel_name}_lower_bound"] - st.session_state['scenario'].update_bounds_max(channel_name,modified_bounds) + st.session_state["scenario"].update_bounds_max(channel_name, modified_bounds) # st.write(st.session_state["scenario"].channels[channel_name].channel_bounds_max) # st.write(st.session_state["scenario"].channels[channel_name]) - + + def update_data_by_percent(channel_name): prev_spends = ( st.session_state["scenario"].channels[channel_name].actual_total_spends @@ -468,19 +507,19 @@ def update_data(channel_name): modified_spends / st.session_state["scenario"].channels[channel_name].conversion_rate, ) -# st.write(hasattr(st.session_state["scenario"], 'update_bounds_min')) - # st.session_state['scenario'].update(channel_name, modified_spends) - # else: - # try: - # modified_spends = float(st.session_state[channel_name]) - # prev_spends = st.session_state['scenario'].channels[channel_name].actual_total_spends * st.session_state['scenario'].channels[channel_name].conversion_rate - # st.session_state[f'{channel_name}_change'] = round(100*(modified_spends - prev_spends) / prev_spends,2) - # st.session_state['scenario'].update(channel_name, modified_spends/st.session_state['scenario'].channels[channel_name].conversion_rate) - # st.session_state[f'{channel_name}'] = numerize(modified_spends,1) - # except ValueError: - # st.write('Invalid input') +# st.write(hasattr(st.session_state["scenario"], 'update_bounds_min')) +# st.session_state['scenario'].update(channel_name, modified_spends) +# else: +# try: +# modified_spends = float(st.session_state[channel_name]) +# prev_spends = st.session_state['scenario'].channels[channel_name].actual_total_spends * st.session_state['scenario'].channels[channel_name].conversion_rate +# st.session_state[f'{channel_name}_change'] = round(100*(modified_spends - prev_spends) / prev_spends,2) +# st.session_state['scenario'].update(channel_name, modified_spends/st.session_state['scenario'].channels[channel_name].conversion_rate) +# st.session_state[f'{channel_name}'] = numerize(modified_spends,1) +# except ValueError: +# st.write('Invalid input') def select_channel_for_optimization(channel_name): @@ -494,6 +533,7 @@ def select_channel_for_optimization(channel_name): # if not all(st.session_state["optimization_channels"].values()): # st.session_state["optimize_all_channels"] = False + def select_all_channels_for_optimization(): """ Marks all the channel for optimization @@ -505,7 +545,6 @@ def select_all_channels_for_optimization(): st.session_state["optimization_channels"][channel_name] = st.session_state[ "optimze_all_channels" ] - def update_penalty(): @@ -524,7 +563,6 @@ def reset_scenario(panel_selected, file_selected, updated_rcs): if panel_selected == "Total Market": initialize_data( - target_file=file_selected, panel=panel_selected, updated_rcs=updated_rcs, @@ -533,7 +571,6 @@ def reset_scenario(panel_selected, file_selected, updated_rcs): panel = None else: initialize_data( - target_file=file_selected, panel=panel_selected, updated_rcs=updated_rcs, @@ -681,32 +718,47 @@ def plot_response_curves(summary_df_sorted): # shapes = [] # fig = make_subplots(rows=rows, cols=cols, subplot_titles=channels_list) channel_cols = [ - 'BroadcastTV', - 'CableTV', - 'Connected&OTTTV', - 'DisplayProspecting', - 'DisplayRetargeting', - 'Video', - 'SocialProspecting', - 'SocialRetargeting', - 'SearchBrand', - 'SearchNon-brand', - 'DigitalPartners', - 'Audio', - 'Email'] + "BroadcastTV", + "CableTV", + "Connected&OTTTV", + "DisplayProspecting", + "DisplayRetargeting", + "Video", + "SocialProspecting", + "SocialRetargeting", + "SearchBrand", + "SearchNon-brand", + "DigitalPartners", + "Audio", + "Email", + ] summary_df_sorted.index = summary_df_sorted["Channel_name"] - figures = [rc.response_curves(channels_list[i], summary_df_sorted["Optimized_spend"][channels_list[i]], summary_df_sorted["New_sales"][channels_list[i]]) for i in range(13)] + figures = [ + rc.response_curves( + channels_list[i], + summary_df_sorted["Optimized_spend"][channels_list[i]], + summary_df_sorted["New_sales"][channels_list[i]], + ) + for i in range(13) + ] # for i in range() - + # Display figures in a grid layout - cols = st.columns(3) # 4 columns for the grid + col_num = 3 + cols = st.columns(col_num) # 4 columns for the grid for idx, fig in enumerate(figures): - col = cols[idx % 3] + col = cols[idx % col_num] with col: + # Get the current title and replace 'Response Curve' with a space + current_title = fig.layout.title.text if fig.layout.title else "" + updated_title = current_title.replace("Response Curve", "").strip().replace("Connected & OTTTV", "Connected & OTT TV") + + fig.update_layout(height=350, width=350, yaxis_title="Revenue", title=updated_title) st.plotly_chart(fig, use_container_width=True) + # ======================================================== # # ==================== HTML Components =================== # # ======================================================== # @@ -714,7 +766,8 @@ def plot_response_curves(summary_df_sorted): def generate_spending_header(heading): return st.markdown( - f"""

{heading}

""", unsafe_allow_html=True + f"""

{heading}

""", + unsafe_allow_html=True, ) @@ -740,25 +793,34 @@ auth_status = st.session_state.get("authentication_status") import os import glob + def upload_file_prospects_calc(df): df["Prospects"] = 0 - params = pd.read_excel(r"response_curves_parameters.xlsx",index_col = "channel") + params = pd.read_excel(r"response_curves_parameters.xlsx", index_col="channel") param_dicts = {col: params[col].to_dict() for col in params.columns} df.index = df.channel -# # # # print(param_dicts) + # # # # print(param_dicts) for col in df.channel: x = df["Spends"][col] dividing_rate = 104 # st.write(x) - x_inp = ( x/dividing_rate- param_dicts["x_min"][col]) / (param_dicts["x_max"][col] - param_dicts["x_min"][col]) - x_out = x_inp**param_dicts["n"][col] / (param_dicts["Kd"][col]**param_dicts["n"][col] + x_inp**param_dicts["n"][col]) #self.hill_equation(x_inp,Kd, n) - # # # # print("x_out",x_out) - - - x_val_inv = (x_out*param_dicts["x_max"][col] + (1 - x_out) * param_dicts["x_min"][col]) - sales = (x_val_inv*param_dicts["y_min"][col]/param_dicts["y_max"][col])*dividing_rate - # sales = ((x_max - x_min)*x_out + x_min)*dividing_rate + x_inp = (x / dividing_rate - param_dicts["x_min"][col]) / ( + param_dicts["x_max"][col] - param_dicts["x_min"][col] + ) + x_out = x_inp ** param_dicts["n"][col] / ( + param_dicts["Kd"][col] ** param_dicts["n"][col] + + x_inp ** param_dicts["n"][col] + ) # self.hill_equation(x_inp,Kd, n) + # # # # print("x_out",x_out) + + x_val_inv = ( + x_out * param_dicts["x_max"][col] + (1 - x_out) * param_dicts["x_min"][col] + ) + sales = ( + x_val_inv * param_dicts["y_min"][col] / param_dicts["y_max"][col] + ) * dividing_rate + # sales = ((x_max - x_min)*x_out + x_min)*dividing_rate # x = (df["Spends"][col]/104 - param_dicts["x_min"][col])/(param_dicts["x_max"][col]-param_dicts["x_min"][col]) # x_out = x**param_dicts["n"][col]/(param_dicts["Kd"][col]**param_dicts["n"][col]+ x**param_dicts["n"][col]) @@ -766,7 +828,7 @@ def upload_file_prospects_calc(df): df["Prospects"][col] = sales # # # # print(df) return df - + def upload_file_format(df): # key_df = pd.DataFrame() @@ -777,42 +839,44 @@ def upload_file_format(df): # # st.dataframe(df) # df["channel"] = df["channels"] # df.drop(columns = ["channel"]) - + df1 = df.transpose() - df1.reset_index(inplace = True) - df1.columns = df1.iloc[0] + df1.reset_index(inplace=True) + df1.columns = df1.iloc[0] df1 = df1[1:] - df1["channel"] = pd.to_datetime('1999-08-06').date() - df1.rename(columns = {"channel":"Date"},inplace = True) - - df2 = df1.rename(columns = {"Date":"Week"}) + df1["channel"] = pd.to_datetime("1999-08-06").date() + df1.rename(columns={"channel": "Date"}, inplace=True) + + df2 = df1.rename(columns={"Date": "Week"}) - df3 =upload_file_prospects_calc(df) + df3 = upload_file_prospects_calc(df) df3 = df3[["Prospects"]].transpose().reset_index() - df3["index"] = pd.to_datetime('1999-08-06').date() - df3.rename(columns = {"index":"Date"},inplace = True) - df3.insert(1, 'const', [0]) - + df3["index"] = pd.to_datetime("1999-08-06").date() + df3.rename(columns={"index": "Date"}, inplace=True) + df3.insert(1, "const", [0]) + # st.dataframe(df3) # Create a buffer to hold the Excel file import io + output = io.BytesIO() # Write the dataframes to an Excel file - with pd.ExcelWriter(output, engine='openpyxl') as writer: - df1.to_excel(writer, index=False, sheet_name='RAW DATA MMM') - df2.to_excel(writer, index=False, sheet_name='SPEND INPUT') - df3.to_excel(writer, index=False, sheet_name='CONTRIBUTION MMM') + with pd.ExcelWriter(output, engine="openpyxl") as writer: + df1.to_excel(writer, index=False, sheet_name="RAW DATA MMM") + df2.to_excel(writer, index=False, sheet_name="SPEND INPUT") + df3.to_excel(writer, index=False, sheet_name="CONTRIBUTION MMM") # Seek to the beginning of the stream output.seek(0) - with open('Overview_data_uploaded.xlsx', 'wb') as f: + with open("Overview_data_uploaded.xlsx", "wb") as f: f.write(output.getvalue()) return + def get_excel_names(directory): # Create a list to hold the final parts of the filenames last_portions = [] @@ -880,109 +944,169 @@ def reset_inputs(): st.session_state["initialized"] = False + def scenario_planner_plots2(): import plotly.graph_objects as go from plotly.subplots import make_subplots - - with open('summary_df.pkl', 'rb') as file: - summary_df_sorted = pickle.load(file) - #st.write(summary_df_sorted) - - # selected_scenario= st.selectbox('Select Saved Scenarios',['S1','S2']) - summary_df_sorted=summary_df_sorted.sort_values(by=['Optimized_spend'],ascending=False) - summary_df_sorted['old_efficiency']=(summary_df_sorted['Old_sales']/summary_df_sorted['Old_sales'].sum())/(summary_df_sorted['Actual_spend']/summary_df_sorted['Actual_spend'].sum()) - summary_df_sorted['new_efficiency']=(summary_df_sorted['New_sales']/summary_df_sorted['New_sales'].sum())/(summary_df_sorted['Optimized_spend']/summary_df_sorted['Optimized_spend'].sum()) - summary_df_sorted['old_roi']=summary_df_sorted['Old_sales']/summary_df_sorted['Actual_spend'] - summary_df_sorted['new_roi']=summary_df_sorted['New_sales']/summary_df_sorted['Optimized_spend'] - - total_actual_spend = summary_df_sorted['Actual_spend'].sum() - total_optimized_spend = summary_df_sorted['Optimized_spend'].sum() - actual_spend_percentage = (summary_df_sorted['Actual_spend'] / total_actual_spend) * 100 - optimized_spend_percentage = (summary_df_sorted['Optimized_spend'] / total_optimized_spend) * 100 - + with open("summary_df.pkl", "rb") as file: + summary_df_sorted = pickle.load(file) + # st.write(summary_df_sorted) + # selected_scenario= st.selectbox('Select Saved Scenarios',['S1','S2']) + summary_df_sorted = summary_df_sorted.sort_values( + by=["Optimized_spend"], ascending=False + ) + summary_df_sorted["old_efficiency"] = ( + summary_df_sorted["Old_sales"] / summary_df_sorted["Old_sales"].sum() + ) / (summary_df_sorted["Actual_spend"] / summary_df_sorted["Actual_spend"].sum()) + summary_df_sorted["new_efficiency"] = ( + summary_df_sorted["New_sales"] / summary_df_sorted["New_sales"].sum() + ) / ( + summary_df_sorted["Optimized_spend"] + / summary_df_sorted["Optimized_spend"].sum() + ) + summary_df_sorted["old_roi"] = ( + summary_df_sorted["Old_sales"] / summary_df_sorted["Actual_spend"] + ) + summary_df_sorted["new_roi"] = ( + summary_df_sorted["New_sales"] / summary_df_sorted["Optimized_spend"] + ) - light_blue = 'rgba(0, 31, 120, 0.7)' - light_orange = 'rgba(0, 181, 219, 0.7)' - light_green = 'rgba(240, 61, 20, 0.7)' - light_red = 'rgba(250, 110, 10, 0.7)' - light_purple = 'rgba(255, 191, 69, 0.7)' + total_actual_spend = summary_df_sorted["Actual_spend"].sum() + total_optimized_spend = summary_df_sorted["Optimized_spend"].sum() + actual_spend_percentage = ( + summary_df_sorted["Actual_spend"] / total_actual_spend + ) * 100 + optimized_spend_percentage = ( + summary_df_sorted["Optimized_spend"] / total_optimized_spend + ) * 100 + + light_blue = "rgba(0, 31, 120, 0.7)" + light_orange = "rgba(0, 181, 219, 0.7)" + light_green = "rgba(240, 61, 20, 0.7)" + light_red = "rgba(250, 110, 10, 0.7)" + light_purple = "rgba(255, 191, 69, 0.7)" fig1 = go.Figure() - # Add actual vs optimized spend bars + # Add actual vs optimized spend bars + + fig1.add_trace( + go.Bar( + x=summary_df_sorted["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted["Actual_spend"], + name="Actual", + text=summary_df_sorted["Actual_spend"].apply(format_number) + " " + # + + # ' '+ + # '
(' + actual_spend_percentage.astype(int).astype(str) + '%)' + , + textposition="outside", # textfont=dict(size=30), + marker_color=light_blue, + ) + ) + + fig1.add_trace( + go.Bar( + x=summary_df_sorted["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted["Optimized_spend"], + name="Optimized", + text=summary_df_sorted["Optimized_spend"].apply(format_number) + " " + # + + # '
(' + optimized_spend_percentage.astype(int).astype(str) + '%)' + , + textposition="outside", # textfont=dict(size=30), + marker_color=light_orange, + ) + ) - - fig1.add_trace(go.Bar(x=summary_df_sorted['Channel_name'].apply(channel_name_formating), y=summary_df_sorted['Actual_spend'], name='Actual', - text=summary_df_sorted['Actual_spend'].apply(format_number) + ' ' - # + - # ' '+ - # '
(' + actual_spend_percentage.astype(int).astype(str) + '%)' - ,textposition='outside',#textfont=dict(size=30), - marker_color=light_blue)) - - - fig1.add_trace(go.Bar(x=summary_df_sorted['Channel_name'].apply(channel_name_formating), y=summary_df_sorted['Optimized_spend'], name='Optimized', - text=summary_df_sorted['Optimized_spend'].apply(format_number) + ' ' - # + - # '
(' + optimized_spend_percentage.astype(int).astype(str) + '%)' - ,textposition='outside',#textfont=dict(size=30), - marker_color=light_orange)) - fig1.update_xaxes(title_text="Channels") fig1.update_yaxes(title_text="Spends ($)") fig1.update_layout( - title = "Actual vs. Optimized Spends", - margin=dict(t=40, b=40, l=40, r=40) - ) - - # st.plotly_chart(fig1,use_container_width=True) + title="Actual vs. Optimized Spends", margin=dict(t=40, b=40, l=40, r=40) + ) + + # st.plotly_chart(fig1,use_container_width=True) - # Add actual vs optimized Contribution + # Add actual vs optimized Contribution fig2 = go.Figure() - fig2.add_trace(go.Bar(x=summary_df_sorted['Channel_name'].apply(channel_name_formating), y=summary_df_sorted['Old_sales'], - name='Actual Contribution',text=summary_df_sorted['Old_sales'].apply(format_number),textposition='outside', - marker_color=light_blue,showlegend=True)) - - fig2.add_trace(go.Bar(x=summary_df_sorted['Channel_name'].apply(channel_name_formating), y=summary_df_sorted['New_sales'], - name='Optimized Contribution',text=summary_df_sorted['New_sales'].apply(format_number),textposition='outside', - marker_color=light_orange, showlegend=True)) - - - + fig2.add_trace( + go.Bar( + x=summary_df_sorted["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted["Old_sales"], + name="Actual Contribution", + text=summary_df_sorted["Old_sales"].apply(format_number), + textposition="outside", + marker_color=light_blue, + showlegend=True, + ) + ) + + fig2.add_trace( + go.Bar( + x=summary_df_sorted["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted["New_sales"], + name="Optimized Contribution", + text=summary_df_sorted["New_sales"].apply(format_number), + textposition="outside", + marker_color=light_orange, + showlegend=True, + ) + ) + fig2.update_yaxes(title_text="Contribution") - fig2.update_xaxes(title_text="Channels") + fig2.update_xaxes(title_text="Channels") fig2.update_layout( - title = "Actual vs. Optimized Contributions", - margin=dict(t=40, b=40, l=40, r=40) - # yaxis=dict(range=[0, 0.002]), - ) - # st.plotly_chart(fig2,use_container_width=True) + title="Actual vs. Optimized Contributions", + margin=dict(t=40, b=40, l=40, r=40), + # yaxis=dict(range=[0, 0.002]), + ) + # st.plotly_chart(fig2,use_container_width=True) - # Add actual vs optimized Efficiency bars + # Add actual vs optimized Efficiency bars fig3 = go.Figure() - summary_df_sorted_p = summary_df_sorted[summary_df_sorted['Channel_name']!="Panel"] - fig3.add_trace(go.Bar(x=summary_df_sorted_p['Channel_name'].apply(channel_name_formating), y=summary_df_sorted_p['old_efficiency'], - name='Actual Efficiency', text=summary_df_sorted_p['old_efficiency'].apply(format_number) ,textposition='outside', - marker_color=light_blue,showlegend=True)) - fig3.add_trace(go.Bar(x=summary_df_sorted_p['Channel_name'].apply(channel_name_formating), y=summary_df_sorted_p['new_efficiency'], - name='Optimized Efficiency',text=summary_df_sorted_p['new_efficiency'].apply(format_number),textposition='outside' , - marker_color=light_orange,showlegend=True)) - + summary_df_sorted_p = summary_df_sorted[ + summary_df_sorted["Channel_name"] != "Panel" + ] + fig3.add_trace( + go.Bar( + x=summary_df_sorted_p["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted_p["old_efficiency"], + name="Actual Efficiency", + text=summary_df_sorted_p["old_efficiency"].apply(format_number), + textposition="outside", + marker_color=light_blue, + showlegend=True, + ) + ) + fig3.add_trace( + go.Bar( + x=summary_df_sorted_p["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted_p["new_efficiency"], + name="Optimized Efficiency", + text=summary_df_sorted_p["new_efficiency"].apply(format_number), + textposition="outside", + marker_color=light_orange, + showlegend=True, + ) + ) + fig3.update_xaxes(title_text="Channels") fig3.update_yaxes(title_text="Efficiency") fig3.update_layout( - title = "Actual vs. Optimized Efficiency", - margin=dict(t=40, b=40, l=40, r=40), - # yaxis=dict(range=[0, 0.002]), - ) - - # st.plotly_chart(fig3,use_container_width=True) - return fig1,fig2,fig3 + title="Actual vs. Optimized Efficiency", + margin=dict(t=40, b=40, l=40, r=40), + # yaxis=dict(range=[0, 0.002]), + ) + + # st.plotly_chart(fig3,use_container_width=True) + return fig1, fig2, fig3 + + def scenario_planner_plots(): - with st.expander('Optimized Spends Overview'): - # if st.button('Refresh'): - # st.experimental_rerun() + with st.expander("Actual vs. Optimized Comparison"): + # if st.button('Refresh'): + # st.experimental_rerun() import plotly.graph_objects as go from plotly.subplots import make_subplots @@ -992,137 +1116,210 @@ def scenario_planner_plots(): from plotly.subplots import make_subplots st.empty() - #st.header('Model Result Analysis') - spends_data=pd.read_excel('Overview_data_test.xlsx') - - with open('summary_df.pkl', 'rb') as file: - summary_df_sorted = pickle.load(file) - #st.write(summary_df_sorted) - - # selected_scenario= st.selectbox('Select Saved Scenarios',['S1','S2']) - summary_df_sorted=summary_df_sorted.sort_values(by=['Optimized_spend'],ascending=False) - summary_df_sorted['old_efficiency']=(summary_df_sorted['Old_sales']/summary_df_sorted['Old_sales'].sum())/(summary_df_sorted['Actual_spend']/summary_df_sorted['Actual_spend'].sum()) - summary_df_sorted['new_efficiency']=(summary_df_sorted['New_sales']/summary_df_sorted['New_sales'].sum())/(summary_df_sorted['Optimized_spend']/summary_df_sorted['Optimized_spend'].sum()) + # st.header('Model Result Analysis') + spends_data = pd.read_excel("Overview_data_test.xlsx") - summary_df_sorted['old_roi']=summary_df_sorted['Old_sales']/summary_df_sorted['Actual_spend'] - summary_df_sorted['new_roi']=summary_df_sorted['New_sales']/summary_df_sorted['Optimized_spend'] + with open("summary_df.pkl", "rb") as file: + summary_df_sorted = pickle.load(file).copy() + # st.write(summary_df_sorted) - total_actual_spend = summary_df_sorted['Actual_spend'].sum() - total_optimized_spend = summary_df_sorted['Optimized_spend'].sum() + # selected_scenario= st.selectbox('Select Saved Scenarios',['S1','S2']) + summary_df_sorted = summary_df_sorted.sort_values( + by=["Optimized_spend"], ascending=False + ) + summary_df_sorted["old_efficiency"] = ( + summary_df_sorted["Old_sales"] / summary_df_sorted["Old_sales"].sum() + ) / ( + summary_df_sorted["Actual_spend"] / summary_df_sorted["Actual_spend"].sum() + ) + summary_df_sorted["new_efficiency"] = ( + summary_df_sorted["New_sales"] / summary_df_sorted["New_sales"].sum() + ) / ( + summary_df_sorted["Optimized_spend"] + / summary_df_sorted["Optimized_spend"].sum() + ) - actual_spend_percentage = (summary_df_sorted['Actual_spend'] / total_actual_spend) * 100 - optimized_spend_percentage = (summary_df_sorted['Optimized_spend'] / total_optimized_spend) * 100 + summary_df_sorted["old_roi"] = ( + summary_df_sorted["Old_sales"] / summary_df_sorted["Actual_spend"] + ) + summary_df_sorted["new_roi"] = ( + summary_df_sorted["New_sales"] / summary_df_sorted["Optimized_spend"] + ) + total_actual_spend = summary_df_sorted["Actual_spend"].sum() + total_optimized_spend = summary_df_sorted["Optimized_spend"].sum() + actual_spend_percentage = ( + summary_df_sorted["Actual_spend"] / total_actual_spend + ) * 100 + optimized_spend_percentage = ( + summary_df_sorted["Optimized_spend"] / total_optimized_spend + ) * 100 - light_blue = 'rgba(0, 31, 120, 0.7)' - light_orange = 'rgba(0, 181, 219, 0.7)' - light_green = 'rgba(240, 61, 20, 0.7)' - light_red = 'rgba(250, 110, 10, 0.7)' - light_purple = 'rgba(255, 191, 69, 0.7)' + light_blue = "rgba(0, 31, 120, 0.7)" + light_orange = "rgba(0, 181, 219, 0.7)" + light_green = "rgba(240, 61, 20, 0.7)" + light_red = "rgba(250, 110, 10, 0.7)" + light_purple = "rgba(255, 191, 69, 0.7)" fig1 = go.Figure() # Add actual vs optimized spend bars - - fig1.add_trace(go.Bar(x=summary_df_sorted['Channel_name'].apply(channel_name_formating), y=summary_df_sorted['Actual_spend'], name='Actual', - text=summary_df_sorted['Actual_spend'].apply(format_number) + ' ' - # + - # ' '+ - # '
(' + actual_spend_percentage.astype(int).astype(str) + '%)' - ,textposition='outside',#textfont=dict(size=30), - marker_color=light_blue)) - - - fig1.add_trace(go.Bar(x=summary_df_sorted['Channel_name'].apply(channel_name_formating), y=summary_df_sorted['Optimized_spend'], name='Optimized', - text=summary_df_sorted['Optimized_spend'].apply(format_number) + ' ' - # + - # '
(' + optimized_spend_percentage.astype(int).astype(str) + '%)' - ,textposition='outside',#textfont=dict(size=30), - marker_color=light_orange)) - + fig1.add_trace( + go.Bar( + x=summary_df_sorted["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted["Actual_spend"], + name="Actual", + text=summary_df_sorted["Actual_spend"].apply(format_number) + " " + # + + # ' '+ + # '
(' + actual_spend_percentage.astype(int).astype(str) + '%)' + , + textposition="outside", # textfont=dict(size=30), + marker_color=light_blue, + ) + ) + + fig1.add_trace( + go.Bar( + x=summary_df_sorted["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted["Optimized_spend"], + name="Optimized", + text=summary_df_sorted["Optimized_spend"].apply(format_number) + " " + # + + # '
(' + optimized_spend_percentage.astype(int).astype(str) + '%)' + , + textposition="outside", # textfont=dict(size=30), + marker_color=light_orange, + ) + ) + fig1.update_xaxes(title_text="Channels") fig1.update_yaxes(title_text="Spends ($)") fig1.update_layout( - title = "Actual vs. Optimized Spends", - margin=dict(t=40, b=40, l=40, r=40) - ) - - st.plotly_chart(fig1,use_container_width=True) + title="Spends", margin=dict(t=40, b=40, l=40, r=40) + ) + + st.plotly_chart(fig1, use_container_width=True) - # Add actual vs optimized Contribution + # Add actual vs optimized Contribution fig2 = go.Figure() - fig2.add_trace(go.Bar(x=summary_df_sorted['Channel_name'].apply(channel_name_formating), y=summary_df_sorted['Old_sales'], - name='Actual Contribution',text=summary_df_sorted['Old_sales'].apply(format_number),textposition='outside', - marker_color=light_blue,showlegend=True)) - - fig2.add_trace(go.Bar(x=summary_df_sorted['Channel_name'].apply(channel_name_formating), y=summary_df_sorted['New_sales'], - name='Optimized Contribution',text=summary_df_sorted['New_sales'].apply(format_number),textposition='outside', - marker_color=light_orange, showlegend=True)) - - - - fig2.update_yaxes(title_text="Contribution") - fig2.update_xaxes(title_text="Channels") + fig2.add_trace( + go.Bar( + x=summary_df_sorted["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted["Old_sales"], + name="Actual Contribution", + text=summary_df_sorted["Old_sales"].apply(format_number), + textposition="outside", + marker_color=light_blue, + showlegend=True, + ) + ) + + fig2.add_trace( + go.Bar( + x=summary_df_sorted["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted["New_sales"], + name="Optimized Contribution", + text=summary_df_sorted["New_sales"].apply(format_number), + textposition="outside", + marker_color=light_orange, + showlegend=True, + ) + ) + + fig2.update_yaxes(title_text="Revenue ($)") + fig2.update_xaxes(title_text="Channels") fig2.update_layout( - title = "Actual vs. Optimized Contributions", - margin=dict(t=40, b=40, l=40, r=40) - # yaxis=dict(range=[0, 0.002]), - ) - st.plotly_chart(fig2,use_container_width=True) + title="Revenue", + margin=dict(t=40, b=40, l=40, r=40), + # yaxis=dict(range=[0, 0.002]), + ) + st.plotly_chart(fig2, use_container_width=True) # Add actual vs optimized Efficiency bars fig3 = go.Figure() - summary_df_sorted_p = summary_df_sorted[summary_df_sorted['Channel_name']!="Panel"] - fig3.add_trace(go.Bar(x=summary_df_sorted_p['Channel_name'].apply(channel_name_formating), y=summary_df_sorted_p['old_efficiency'], - name='Actual Efficiency', text=summary_df_sorted_p['old_efficiency'].apply(format_number) ,textposition='outside', - marker_color=light_blue,showlegend=True)) - fig3.add_trace(go.Bar(x=summary_df_sorted_p['Channel_name'].apply(channel_name_formating), y=summary_df_sorted_p['new_efficiency'], - name='Optimized Efficiency',text=summary_df_sorted_p['new_efficiency'].apply(format_number),textposition='outside' , - marker_color=light_orange,showlegend=True)) - + summary_df_sorted_p = summary_df_sorted[ + summary_df_sorted["Channel_name"] != "Panel" + ] + + # Ensure there are no division-by-zero errors + summary_df_sorted_p["Actual_spend"].replace(0, np.nan, inplace=True) + summary_df_sorted_p["Optimized_spend"].replace(0, np.nan, inplace=True) + + summary_df_sorted_p["old_roi"] = summary_df_sorted_p["Old_sales"] / summary_df_sorted_p["Actual_spend"] + summary_df_sorted_p["new_roi"] = summary_df_sorted_p["New_sales"] / summary_df_sorted_p["Optimized_spend"] + + + fig3.add_trace( + go.Bar( + x=summary_df_sorted_p["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted_p["old_roi"], + name="Actual ROI", + text=summary_df_sorted_p["old_roi"].apply(format_number), + textposition="outside", + marker_color=light_blue, + showlegend=True, + ) + ) + + fig3.add_trace( + go.Bar( + x=summary_df_sorted_p["Channel_name"].apply(channel_name_formating), + y=summary_df_sorted_p["new_roi"], + name="Optimized ROI", + text=summary_df_sorted_p["new_roi"].apply(format_number), + textposition="outside", + marker_color=light_orange, + showlegend=True, + ) + ) + fig3.update_xaxes(title_text="Channels") - fig3.update_yaxes(title_text="Efficiency") + fig3.update_yaxes(title_text="ROI") fig3.update_layout( - title = "Actual vs. Optimized Efficiency", - margin=dict(t=40, b=40, l=40, r=40), - # yaxis=dict(range=[0, 0.002]), - ) - - st.plotly_chart(fig3,use_container_width=True) - return fig1,fig2,fig3 + title="ROI", + margin=dict(t=40, b=40, l=40, r=40), + # yaxis=dict(range=[0, 0.002]), + ) + + st.plotly_chart(fig3, use_container_width=True) + return fig1, fig2, fig3 + def give_demo(): def get_file_bytes(file_path): - with open(file_path, 'rb') as file: + with open(file_path, "rb") as file: return file.read() # Path to the existing Excel file - file_path = 'input_data_example.xlsx' + file_path = "input_data_example.xlsx" # Create a download button st.download_button( label="Download Input File Format", data=get_file_bytes(file_path), file_name=file_path, - mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" - ) + mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + ) + + if auth_status == True: authenticator.logout("Logout", "main") st.header("Scenario Planner") - + data_selected = st.selectbox( - "Select base data for optimisation", options=["Optimise Actual Spends", "Optimise Uploaded Spends"], - key = "data_upload_key",index = 1) + "Select base data for optimisation", + options=["Optimise Actual Spends", "Optimise Uploaded Spends"], + key="data_upload_key", + index=1, + ) # st.text_input("") - - - # Response Metrics directory = "metrics_level_data" metrics_list = get_excel_names(directory) - + # metrics_selected = col1.selectbox( # "Response Metrics", # metrics_list, @@ -1131,7 +1328,7 @@ if auth_status == True: # on_change=reset_inputs, # ) - metrics_selected='prospects' + metrics_selected = "prospects" # Target target = name_formating(metrics_selected) @@ -1139,21 +1336,21 @@ if auth_status == True: # f"Overview_data_test_panel@#{metrics_selected}.xlsx" # ) file_selected = None - if data_selected == "Optimise Uploaded Spends": + if data_selected == "Optimise Uploaded Spends": give_demo() st.write("Select a file to upload") - + uploaded_file = st.file_uploader("Choose an Excel file", type=["xlsx", "xls"]) # give_demo() if uploaded_file: try: # Read the Excel file using pandas - df = pd.read_excel(uploaded_file, engine='openpyxl') + df = pd.read_excel(uploaded_file, engine="openpyxl") upload_file_format(df) file_selected = "Overview_data_uploaded.xlsx" # initialize_data( - + # target_file=file_selected, # panel="Total Market", # updated_rcs=None, @@ -1161,24 +1358,22 @@ if auth_status == True: # ) except Exception as e: st.error(f"Error reading the file: {e}") - - elif data_selected == "Optimise Actual Spends": - file_selected = ( - f"Overview_data_test_panel@#{metrics_selected}.xlsx" - ) + + elif data_selected == "Optimise Actual Spends": + file_selected = f"Overview_data_test_panel@#{metrics_selected}.xlsx" # initialize_data( - + # target_file=file_selected, # panel="Total Market", # updated_rcs=None, # metrics=metrics_selected, # ) - - else : + + else: st.write("") if file_selected: - st.session_state['file_selected']=file_selected + st.session_state["file_selected"] = file_selected # Panel List panel_list = panel_fetch(file_selected) @@ -1189,10 +1384,10 @@ if auth_status == True: # index=0, # on_change=reset_inputs, # ) - + # st.write(panel_selected) panel_selected = "Total Market" - st.session_state['selected_markets']=panel_selected + st.session_state["selected_markets"] = panel_selected if "update_rcs" in st.session_state: updated_rcs = st.session_state["update_rcs"] @@ -1206,18 +1401,15 @@ if auth_status == True: is_state_initiaized = st.session_state.get("initialized", False) if not is_state_initiaized or st.session_state["first_time"]: initialize_data( - - target_file=file_selected, - panel=panel_selected, - updated_rcs=updated_rcs, - metrics=metrics_selected, - ) + target_file=file_selected, + panel=panel_selected, + updated_rcs=updated_rcs, + metrics=metrics_selected, + ) st.session_state["initialized"] = True st.session_state["first_time"] = False save_scenario("current scenario") - - # initialize_data( # panel=panel_selected, # target_file=file_selected, @@ -1265,29 +1457,46 @@ if auth_status == True: st.session_state.total_sales_change_abs_slider = numerize( _scenario.actual_total_sales, 1 ) - + if "lower_bound_key" not in st.session_state: st.session_state["lower_bound_key"] = 10 - + if "upper_bound_key" not in st.session_state: st.session_state["upper_bound_key"] = 100 # st.write(_scenario.modified_total_sales) - header_df = pd.DataFrame(index=["Actual","Simulated","Change","Percent Change"],columns=["Spends","Prospects"]) + header_df = pd.DataFrame( + index=["Actual", "Simulated", "Change", "Percent Change"], + columns=["Spends", "Prospects"], + ) header_df["Spends"]["Actual"] = format_numbers(_scenario.actual_total_spends) - header_df["Spends"]["Simulated"] = format_numbers(_scenario.modified_total_spends) - header_df["Spends"]["Change"] = format_numbers(_scenario.delta_spends) #_scenario.modified_total_spends -_scenario.actual_total_spends - header_df["Spends"]["Percent Change"] = numerize(100*(_scenario.delta_spends/_scenario.actual_total_spends))+'%' - - header_df["Prospects"]["Actual"] = format_numbers_f(float(_scenario.actual_total_sales)) - header_df["Prospects"]["Simulated"] = format_numbers_f(float(_scenario.modified_total_sales)) + header_df["Spends"]["Simulated"] = format_numbers( + _scenario.modified_total_spends + ) + header_df["Spends"]["Change"] = format_numbers( + _scenario.delta_spends + ) # _scenario.modified_total_spends -_scenario.actual_total_spends + header_df["Spends"]["Percent Change"] = ( + numerize(100 * (_scenario.delta_spends / _scenario.actual_total_spends)) + + "%" + ) + + header_df["Prospects"]["Actual"] = format_numbers_f( + float(_scenario.actual_total_sales) + ) + header_df["Prospects"]["Simulated"] = format_numbers_f( + float(_scenario.modified_total_sales) + ) header_df["Prospects"]["Change"] = format_numbers_f(_scenario.delta_sales) - header_df["Prospects"]["Percent Change"] = numerize(100*(_scenario.delta_sales/_scenario.actual_total_sales),1)+'%' - + header_df["Prospects"]["Percent Change"] = ( + numerize(100 * (_scenario.delta_sales / _scenario.actual_total_sales), 1) + + "%" + ) + st.markdown("""
""", unsafe_allow_html=True) _columns = st.columns((1, 1, 1, 1, 1)) st.markdown( - """ + """ """, - unsafe_allow_html=True - ) + unsafe_allow_html=True, + ) with _columns[0]: - st.markdown(f'

{"Metrics"}

', unsafe_allow_html=True) + st.markdown( + f'

{"Metrics"}

', unsafe_allow_html=True + ) # generate_spending_header("Metric") with _columns[1]: - st.markdown(f'

{"Actual"}

', unsafe_allow_html=True) + st.markdown( + f'

{"Actual"}

', unsafe_allow_html=True + ) # generate_spending_header("Actual") with _columns[2]: - st.markdown(f'

{"Simulated"}

', unsafe_allow_html=True) + st.markdown( + f'

{"Simulated"}

', unsafe_allow_html=True + ) # generate_spending_header("Optimised") with _columns[3]: - st.markdown(f'

{"Change"}

', unsafe_allow_html=True) + st.markdown( + f'

{"Change"}

', unsafe_allow_html=True + ) # generate_spending_header("Change") with _columns[4]: - st.markdown(f'

{"Change Percent"}

', unsafe_allow_html=True) + st.markdown( + f'

{"Change Percent"}

', + unsafe_allow_html=True, + ) # generate_spending_header("Change Percent") st.markdown("""
""", unsafe_allow_html=True) _columns = st.columns((1, 1, 1, 1, 1)) with _columns[0]: - st.markdown("""

Spends

""",unsafe_allow_html=True) + st.markdown("""

Spends

""", unsafe_allow_html=True) # st.write("Spends") with _columns[1]: - st.markdown(f"""

{header_df["Spends"]["Actual"]}

""",unsafe_allow_html=True) + st.markdown( + f"""

{header_df["Spends"]["Actual"]}

""", unsafe_allow_html=True + ) # st.metric(label="", value=header_df["Spends"]["Actual"]) with _columns[2]: - st.markdown(f"""

{header_df["Spends"]["Simulated"]}

""",unsafe_allow_html=True) + st.markdown( + f"""

{header_df["Spends"]["Simulated"]}

""", + unsafe_allow_html=True, + ) if _scenario.delta_spends < 0: - st.markdown( + st.markdown( """ """, - unsafe_allow_html=True + unsafe_allow_html=True, ) else: - st.markdown( + st.markdown( """ """, - unsafe_allow_html=True + unsafe_allow_html=True, ) - # st.metric(label="", value=header_df["Spends"]["Simulated"]) + # st.metric(label="", value=header_df["Spends"]["Simulated"]) with _columns[3]: - + # Apply custom styles to text - st.markdown(f'

{header_df["Spends"]["Change"]}

', unsafe_allow_html=True) + st.markdown( + f'

{header_df["Spends"]["Change"]}

', + unsafe_allow_html=True, + ) with _columns[4]: # Apply custom styles to text # st.markdown(f'

', unsafe_allow_html=True) - st.markdown(f'

{header_df["Spends"]["Percent Change"]}

', unsafe_allow_html=True) + st.markdown( + f'

{header_df["Spends"]["Percent Change"]}

', + unsafe_allow_html=True, + ) st.markdown( - """
""", - unsafe_allow_html=True, - ) + """
""", + unsafe_allow_html=True, + ) _columns = st.columns((1, 1, 1, 1, 1)) with _columns[0]: # st.header("Prospects") - st.markdown("""

Prospects

""",unsafe_allow_html=True) + st.markdown("""

Revenue

""", unsafe_allow_html=True) with _columns[1]: - st.markdown(f"""

{header_df["Prospects"]["Actual"]}

""",unsafe_allow_html=True) + st.markdown( + f"""

$ {header_df["Prospects"]["Actual"]}

""", + unsafe_allow_html=True, + ) # st.metric(label="", value=header_df["Prospects"]["Actual"]) with _columns[2]: - st.markdown(f"""

{header_df["Prospects"]["Simulated"]}

""",unsafe_allow_html=True) + st.markdown( + f"""

$ {header_df["Prospects"]["Simulated"]}

""", + unsafe_allow_html=True, + ) # st.metric(label="", value=header_df["Prospects"]["Simulated"]) - + if _scenario.delta_sales >= 0: - st.markdown( + st.markdown( """ """, - unsafe_allow_html=True + unsafe_allow_html=True, ) else: - st.markdown("""""",unsafe_allow_html=True) + st.markdown( + """""", + unsafe_allow_html=True, + ) with _columns[3]: # Apply custom styles to text - st.markdown(f'

{header_df["Prospects"]["Change"]}

', unsafe_allow_html=True) - # st.markdown(f'

{st.metric(label="", value=header_df["Prospects"]["Change"])}

', unsafe_allow_html=True) - # st.markdown(f'

{header_df["Prospects"]["Change"]}

', unsafe_allow_html=True) + st.markdown( + f'

$ {header_df["Prospects"]["Change"]}

', + unsafe_allow_html=True, + ) + # st.markdown(f'

{st.metric(label="", value=header_df["Prospects"]["Change"])}

', unsafe_allow_html=True) + # st.markdown(f'

{header_df["Prospects"]["Change"]}

', unsafe_allow_html=True) with _columns[4]: # st.markdown(f'

', unsafe_allow_html=True) # Apply custom styles to text - st.markdown(f'

{header_df["Prospects"]["Percent Change"]}

', unsafe_allow_html=True) + st.markdown( + f'

{header_df["Prospects"]["Percent Change"]}

', + unsafe_allow_html=True, + ) st.markdown( - """
""", - unsafe_allow_html=True, - ) - + """
""", + unsafe_allow_html=True, + ) + _columns = st.columns((1, 1, 1, 1, 1)) - ef1 = (_scenario.actual_total_spends/_scenario.actual_total_sales) - ef2 = (_scenario.modified_total_spends/_scenario.modified_total_sales) + + ef1 = _scenario.actual_total_sales/ _scenario.actual_total_spends + ef2 = _scenario.modified_total_sales/ _scenario.modified_total_spends with _columns[0]: - st.markdown("""

Cost Per Prospect

""",unsafe_allow_html=True) + st.markdown("""

ROI

""", unsafe_allow_html=True) # st.header("Cost Per Prospect") with _columns[1]: - st.markdown(f"""

{'$ '+numerize(ef1,0)}

""",unsafe_allow_html=True) + st.markdown(f"""

{numerize(ef1,0)}

""", unsafe_allow_html=True) # st.metric(label="", value='$ '+numerize(ef1,0)) with _columns[2]: - st.markdown(f"""

{'$ '+numerize(ef2,0)}

""",unsafe_allow_html=True) + st.markdown(f"""

{numerize(ef2,0)}

""", unsafe_allow_html=True) # st.metric(label="", value='$ '+numerize(ef2,0)) if ef2 <= ef1: - st.markdown( + st.markdown( """ """, - unsafe_allow_html=True + unsafe_allow_html=True, ) else: - st.markdown( + st.markdown( """ """, - unsafe_allow_html=True + unsafe_allow_html=True, ) with _columns[3]: - - + # Apply custom styles to text - st.markdown(f'

{"$ "+numerize(ef2-ef1,0)}

', unsafe_allow_html=True) - # st.markdown(f'

{st.metric(label="", value=header_df["Prospects"]["Change"])}

', unsafe_allow_html=True) - # st.markdown(f'

{header_df["Prospects"]["Change"]}

', unsafe_allow_html=True) + st.markdown( + f'

{numerize(ef2-ef1,0)}

', + unsafe_allow_html=True, + ) + # st.markdown(f'

{st.metric(label="", value=header_df["Prospects"]["Change"])}

', unsafe_allow_html=True) + # st.markdown(f'

{header_df["Prospects"]["Change"]}

', unsafe_allow_html=True) with _columns[4]: # st.markdown(f'

', unsafe_allow_html=True) # Apply custom styles to text - st.markdown(f'

{round((ef2-ef1)/ef1*100,2)}%

', unsafe_allow_html=True) - st.markdown("""
""",unsafe_allow_html=True) + st.markdown( + f'

{round((ef2-ef1)/ef1*100,2)}%

', + unsafe_allow_html=True, + ) + st.markdown("""
""", unsafe_allow_html=True) # st.markdown("""
""", unsafe_allow_html=True) @@ -1488,14 +1740,14 @@ if auth_status == True: # if row_idx in rows and col_idx > 0: # Exclude the first column (col_idx > 0) # return format_arrows(val) # return '' # No formatting for other cells - + # return df.style.apply(lambda x: [format_cell(val, i, col) for i, (val, col) in enumerate(zip(x, range(len(x))))], axis=1) # # Apply formatting to 3rd and 4th rows (index 2 and 3) # styled_df = apply_row_formatting(header_df, [2, 3]) # st.markdown(styled_df.to_html(escape=False), unsafe_allow_html=True) - + # st.markdown(header_df.style.set_table_styles # ([{'selector': 'th', # 'props': [('background-color', '#D3D3D3'), @@ -1507,17 +1759,14 @@ if auth_status == True: # } # , # {'selector': 'tbody td', - # 'props': [('font-size', '20px')]} + # 'props': [('font-size', '20px')]} - # ]).to_html(),unsafe_allow_html=True) - + # ]).to_html(),unsafe_allow_html=True) - - # styled_df = header_df.style.apply(highlight_first_col, axis=1) + # styled_df = header_df.style.apply(highlight_first_col, axis=1) # st.table(styled_df) - # with main_header[0]: # st.subheader("Actual") @@ -1552,7 +1801,7 @@ if auth_status == True: # ) with st.expander("Channel Spends Simulator", expanded=True): - _columns1 = st.columns((1.5, 1.5, 1,1)) + _columns1 = st.columns((1, 1, 1, 1)) with _columns1[0]: optimization_selection = st.selectbox( "Optimize", options=["Media Spends", target], key="optimization_key" @@ -1567,7 +1816,7 @@ if auth_status == True: # # on_change=select_all_channels_for_optimization, # ): # select_all_channels_for_optimization() - + st.write("#") st.checkbox( label="Optimize all Channels", key="optimze_all_channels", @@ -1576,43 +1825,43 @@ if auth_status == True: ) with _columns1[2]: - # - - - + st.write("####") optimize_placeholder = st.empty() with _columns1[3]: - # st.markdown("#") + st.write("####") st.button( "Reset", on_click=reset_scenario, args=(panel_selected, file_selected, updated_rcs), - # use_container_width=True, + use_container_width=True, ) # st.write(target) - - _columns2 = st.columns((2, 2, 2,2)) + _columns2 = st.columns((2, 2, 2, 2)) if st.session_state["optimization_key"] == "Media Spends": # st.write(overall_lower_bound,overall_upper_bound) - + with _columns2[2]: overall_lower_bound = st.number_input( - "Overall Lower Bound for Spends", - value = 50.0, - key = "overall_lower_bound", - # on_change=partial(update_data_bound_min_overall) - ) + "Overall Lower Bound for Spends", + value=50.0, + key="overall_lower_bound", + # on_change=partial(update_data_bound_min_overall) + ) with _columns2[3]: overall_upper_bound = st.number_input( - "Overall Upper Bound for Spends", - value = 50.0, - key = "overall_upper_bound", - # on_change=partial(update_data_bound_max_overall) - ) - min_value = round(_scenario.actual_total_spends * (1-overall_lower_bound/100)) - max_value = round(_scenario.actual_total_spends * (1-overall_upper_bound/100)) + "Overall Upper Bound for Spends", + value=50.0, + key="overall_upper_bound", + # on_change=partial(update_data_bound_max_overall) + ) + min_value = round( + _scenario.actual_total_spends * (1 - overall_lower_bound / 100) + ) + max_value = round( + _scenario.actual_total_spends * (1 - overall_upper_bound / 100) + ) with _columns2[0]: spend_input = st.text_input( "Absolute", @@ -1627,15 +1876,13 @@ if auth_status == True: st.number_input( "Percent Change", key="total_spends_change", - min_value= -1*overall_lower_bound, - max_value= overall_upper_bound, + min_value=-1 * overall_lower_bound, + max_value=overall_upper_bound, step=0.01, value=0.00, on_change=update_spends, ) - - st.session_state["total_spends_change_abs_slider_options"] = [ numerize(value, 1) for value in range(min_value, max_value + 1, int(1e4)) @@ -1647,7 +1894,7 @@ if auth_status == True: # key="total_spends_change_abs_slider", # on_change=update_all_spends_abs_slider, # ) - + elif st.session_state["optimization_key"] == target: # st.write(target) with _columns2[0]: @@ -1664,24 +1911,25 @@ if auth_status == True: min_value=-50.00, max_value=50.00, step=0.01, - value=0.00, on_change=update_sales, ) with _columns2[2]: - overall_lower_bound = st.number_input( - "Overall Lower Bound for Spends", - value = 50 + overall_lower_bound = st.number_input( + "Overall Lower Bound for Spends", value=50 ) with _columns2[3]: - + overall_upper_bound = st.number_input( - "Overall Upper Bound for Spends", - value = 50 + "Overall Upper Bound for Spends", value=50 ) - min_value = round(_scenario.actual_total_sales * (1-overall_lower_bound/100)) - max_value = round(_scenario.actual_total_sales * (1+overall_upper_bound/100)) + min_value = round( + _scenario.actual_total_sales * (1 - overall_lower_bound / 100) + ) + max_value = round( + _scenario.actual_total_sales * (1 + overall_upper_bound / 100) + ) # st.write(min_value) # st.write(max_value) # for value in range(min_value, max_value + 1, int(100)): @@ -1711,7 +1959,6 @@ if auth_status == True: ): st.warning("Invalid Input") - status_placeholder = st.empty() # if optimize_placeholder.button("Optimize", use_container_width=True): @@ -1722,11 +1969,13 @@ if auth_status == True: "Optimize", on_click=optimize, args=(st.session_state["optimization_key"], status_placeholder), - # use_container_width=True, + use_container_width=True, ) - st.markdown("""
""", unsafe_allow_html=True) - _columns = st.columns((1.5,2.5,2,2, 1)) + st.markdown( + """
""", unsafe_allow_html=True + ) + _columns = st.columns((1.5, 2.5, 2, 2, 1)) with _columns[0]: generate_spending_header("Channel") with _columns[1]: @@ -1734,11 +1983,13 @@ if auth_status == True: with _columns[2]: generate_spending_header("Spends") with _columns[3]: - generate_spending_header(target) + generate_spending_header("Revenue" if target == "Prospects" else target) with _columns[4]: generate_spending_header("Optimize") - st.markdown("""
""", unsafe_allow_html=True) + st.markdown( + """
""", unsafe_allow_html=True + ) if "acutual_predicted" not in st.session_state: st.session_state["acutual_predicted"] = { @@ -1746,8 +1997,8 @@ if auth_status == True: "Actual_spend": [], "Optimized_spend": [], "Delta": [], - "New_sales":[], - "Old_sales":[] + "New_sales": [], + "Old_sales": [], } for i, channel_name in enumerate(channels_list): # st.write(channel_name) @@ -1759,13 +2010,22 @@ if auth_status == True: # st.write(st.session_state["scenario"].channels[channel_name].modified_total_spends) # st.write(st.session_state["scenario"].channels[channel_name].bounds) # st.write(st.session_state["scenario"].channels[channel_name].channel_bounds_min) - - _columns = st.columns((1.5,2.5,2,2, 1)) - response_curve_params = pd.read_excel("response_curves_parameters.xlsx",index_col = "channel") - param_dicts = {col: response_curve_params[col].to_dict() for col in response_curve_params.columns} - + + _columns = st.columns((1.5, 2.5, 2, 2, 1)) + response_curve_params = pd.read_excel( + "response_curves_parameters.xlsx", index_col="channel" + ) + param_dicts = { + col: response_curve_params[col].to_dict() + for col in response_curve_params.columns + } + with _columns[0]: - st.write(channel_name_formating(channel_name)) + st.write( + channel_name_formating(channel_name).replace( + "Connected & OTTTV", "Connected & OTT TV" + ) + ) bin_placeholder = st.container() with _columns[1]: @@ -1789,25 +2049,32 @@ if auth_status == True: key=channel_name, # label_visibility="collapsed", on_change=partial(update_data, channel_name), - ) channel_name_lower_bound = f"{channel_name}_lower_bound" - + if channel_name_lower_bound not in st.session_state: - st.session_state[channel_name_lower_bound] = str(round(param_dicts["x_min"][channel_name]*10400/param_dicts["current_spends"][channel_name])) + st.session_state[channel_name_lower_bound] = str( + round( + param_dicts["x_min"][channel_name] + * 10400 + / param_dicts["current_spends"][channel_name] + ) + ) # st.write(st.session_state[channel_name_lower_bound]) channel_bounds_min = st.text_input( "Lower Bound Percentage", - key = channel_name_lower_bound, - on_change=partial(update_data_bound_min,channel_name) + key=channel_name_lower_bound, + on_change=partial(update_data_bound_min, channel_name), ) # st.write(st.session_state[channel_name_lower_bound]) # if not validate_input_lb(str(channel_bounds_min)): # st.error("Invalid input") if not validate_input(spend_input): st.error("Invalid input") + def calc_min_value(): return float(st.session_state[channel_name_upper_bound]) + channel_name_current = f"{channel_name}_change" with _columns_min[1]: channel_name_upper_bound = f"{channel_name}_upper_bound" @@ -1817,17 +2084,18 @@ if auth_status == True: st.number_input( "Percent Change", key=channel_name_current, - step=1.00,value=0.00, + step=1.00, + value=0.00, on_change=partial(update_data_by_percent, channel_name), - max_value = calc_min_value(), - min_value = -1*float(st.session_state[channel_name_lower_bound]) - + max_value=calc_min_value(), + min_value=-1 + * float(st.session_state[channel_name_lower_bound]), ) - + channel_bounds_max = st.text_input( "Upper Bound Percentage", - key = channel_name_upper_bound, - on_change=partial(update_data_bound_max,channel_name) + key=channel_name_upper_bound, + on_change=partial(update_data_bound_max, channel_name), ) # if not validate_input(channel_bounds_max): # st.error("Invalid input") @@ -1838,7 +2106,8 @@ if auth_status == True: * _channel_class.conversion_rate ) actual_channel_spends = float( - _channel_class.actual_total_spends * _channel_class.conversion_rate + _channel_class.actual_total_spends + * _channel_class.conversion_rate ) spends_delta = float( _channel_class.delta_spends * _channel_class.conversion_rate @@ -1856,7 +2125,10 @@ if auth_status == True: _spend_cols = st.columns(2) with _spend_cols[0]: # st.write("Actual") - st.markdown(f'

Actual

{format_numbers(actual_channel_spends)}

', unsafe_allow_html=True) + st.markdown( + f"

Actual

{format_numbers(actual_channel_spends)}

", + unsafe_allow_html=True, + ) # st.metric( # label="Actual Spends", # value=format_numbers(actual_channel_spends), @@ -1865,7 +2137,10 @@ if auth_status == True: # ) # st.write("Actual") - st.markdown(f'

Change

{format_numbers(spends_delta)}

', unsafe_allow_html=True) + st.markdown( + f"

Change

{format_numbers(spends_delta)}

", + unsafe_allow_html=True, + ) # st.markdown(f'

{format_numbers(spends_delta)}%

', unsafe_allow_html=True) # st.metric( @@ -1875,8 +2150,14 @@ if auth_status == True: # # label_visibility="collapsed", # ) with _spend_cols[1]: - st.markdown(f'

Simulated

{format_numbers(current_channel_spends)}

', unsafe_allow_html=True) - st.markdown(f'

Percent

{numerize(( spends_delta/actual_channel_spends)*100,0) +"%"}

', unsafe_allow_html=True) + st.markdown( + f"

Simulated

{format_numbers(current_channel_spends)}

", + unsafe_allow_html=True, + ) + st.markdown( + f'

Percent

{numerize(( spends_delta/actual_channel_spends)*100,0) +"%"}

', + unsafe_allow_html=True, + ) # st.metric( # label="Simulated Spends", # value=format_numbers(current_channel_spends), @@ -1891,21 +2172,30 @@ if auth_status == True: # # label_visibility="collapsed", # ) - with _columns[3]: # sales current_channel_sales = float(_channel_class.modified_total_sales) actual_channel_sales = float(_channel_class.actual_total_sales) sales_delta = float(_channel_class.delta_sales) - st.session_state["acutual_predicted"]["Old_sales"].append(actual_channel_sales) - st.session_state["acutual_predicted"]["New_sales"].append(current_channel_sales) - #st.write(actual_channel_sales) - + st.session_state["acutual_predicted"]["Old_sales"].append( + actual_channel_sales + ) + st.session_state["acutual_predicted"]["New_sales"].append( + current_channel_sales + ) + # st.write(actual_channel_sales) + _prospect_cols = st.columns(2) with _prospect_cols[0]: # st.write("Actual") - st.markdown(f'

Actual

{format_numbers_f(actual_channel_sales)}

', unsafe_allow_html=True) - st.markdown(f'

Change

{format_numbers_f(sales_delta)}

', unsafe_allow_html=True) + st.markdown( + f"

Actual

{format_numbers_f(actual_channel_sales)}

", + unsafe_allow_html=True, + ) + st.markdown( + f"

Change

{format_numbers_f(sales_delta)}

", + unsafe_allow_html=True, + ) # st.metric( # # target, @@ -1921,8 +2211,14 @@ if auth_status == True: # # label_visibility="collapsed", # ) with _prospect_cols[1]: - st.markdown(f'

Simulated

{format_numbers_f(current_channel_sales)}

', unsafe_allow_html=True) - st.markdown(f'

Percent

{numerize(( _channel_class.delta_sales/actual_channel_sales)*100,0) +"%"}

', unsafe_allow_html=True) + st.markdown( + f"

Simulated

{format_numbers_f(current_channel_sales)}

", + unsafe_allow_html=True, + ) + st.markdown( + f'

Percent

{numerize(( _channel_class.delta_sales/actual_channel_sales)*100,0) +"%"}

', + unsafe_allow_html=True, + ) # st.metric( # label="Simulated Prospects", @@ -1938,8 +2234,6 @@ if auth_status == True: # # label_visibility="collapsed", # ) - - with _columns[4]: # if st.checkbox( @@ -1955,7 +2249,9 @@ if auth_status == True: label="select for optimization", key=f"{channel_name}_selected", value=False, - on_change=partial(select_channel_for_optimization, channel_name), + on_change=partial( + select_channel_for_optimization, channel_name + ), label_visibility="collapsed", ) @@ -1968,17 +2264,19 @@ if auth_status == True: col = channels_list[i] x_actual = st.session_state["scenario"].channels[col].actual_spends x_modified = st.session_state["scenario"].channels[col].modified_spends - # x_modified_total = 0 + # x_modified_total = 0 # for c in channels_list: # # st.write(c) # # st.write(st.session_state["scenario"].channels[c].modified_spends) # x_modified_total = x_modified_total + st.session_state["scenario"].channels[c].modified_spends.sum() # st.write(x_modified_total) - + x_total = x_modified.sum() power = np.ceil(np.log(x_actual.max()) / np.log(10)) - 3 - updated_rcs_key = f"{metrics_selected}#@{panel_selected}#@{channel_name}" + updated_rcs_key = ( + f"{metrics_selected}#@{panel_selected}#@{channel_name}" + ) # if updated_rcs and updated_rcs_key in list(updated_rcs.keys()): # K = updated_rcs[updated_rcs_key]["K"] @@ -2025,7 +2323,7 @@ if auth_status == True: # # st.write(roi) # # st.write(roi[-1]) - + # roi_current, marginal_roi_current = roi[-1], marginal_roi[-1] # x, y, roi, marginal_roi = ( # x[:-1], @@ -2034,7 +2332,7 @@ if auth_status == True: # marginal_roi[:-1], # ) # Drop data for current spends - # # roi_current = + # # roi_current = # start_value, end_value, left_value, right_value = find_segment_value( # x, @@ -2042,7 +2340,7 @@ if auth_status == True: # marginal_roi, # ) - #st.write(roi_current) + # st.write(roi_current) # rgba = calculate_rgba( # start_value, @@ -2056,23 +2354,48 @@ if auth_status == True: summary_df = pd.DataFrame(st.session_state["acutual_predicted"]) # (pd.DataFrame(st.session_state["acutual_predicted"])).to_excel("test.xlsx") # st.dataframe(summary_df) - summary_df.drop_duplicates(subset="Channel_name", keep="last", inplace=True) + summary_df.drop_duplicates( + subset="Channel_name", keep="last", inplace=True + ) # st.dataframe(summary_df) - summary_df_sorted = summary_df.sort_values(by="Delta", ascending=False) summary_df_sorted["Delta_percent"] = np.round( - ((summary_df_sorted["Optimized_spend"] / summary_df_sorted["Actual_spend"]) - 1) + ( + ( + summary_df_sorted["Optimized_spend"] + / summary_df_sorted["Actual_spend"] + ) + - 1 + ) * 100, 2, ) - - summary_df_sorted=summary_df_sorted.sort_values(by=['Optimized_spend'],ascending=False) - summary_df_sorted['old_efficiency']=(summary_df_sorted['Old_sales']/summary_df_sorted['Old_sales'].sum())/(summary_df_sorted['Actual_spend']/summary_df_sorted['Actual_spend'].sum()) - summary_df_sorted['new_efficiency']=(summary_df_sorted['New_sales']/summary_df_sorted['New_sales'].sum())/(summary_df_sorted['Optimized_spend']/summary_df_sorted['Optimized_spend'].sum()) - - a = (summary_df_sorted[summary_df_sorted['Channel_name']== col]).reset_index()['new_efficiency'][0] - b = (summary_df_sorted[summary_df_sorted['Channel_name']== col]).reset_index()['old_efficiency'][0] + + summary_df_sorted = summary_df_sorted.sort_values( + by=["Optimized_spend"], ascending=False + ) + summary_df_sorted["old_efficiency"] = ( + summary_df_sorted["Old_sales"] + / summary_df_sorted["Actual_spend"].sum() + ) / ( + summary_df_sorted["Actual_spend"] + / summary_df_sorted["Actual_spend"].sum() + ) + summary_df_sorted["new_efficiency"] = ( + summary_df_sorted["New_sales"] + / summary_df_sorted["Optimized_spend"].sum() + ) / ( + summary_df_sorted["Optimized_spend"] + / summary_df_sorted["Optimized_spend"].sum() + ) + + a = ( + summary_df_sorted[summary_df_sorted["Channel_name"] == col] + ).reset_index()["new_efficiency"][0] + b = ( + summary_df_sorted[summary_df_sorted["Channel_name"] == col] + ).reset_index()["old_efficiency"][0] # st.write(a) # # print(a) # # print(summary_df_sorted['Actual_spend'].sum()) @@ -2081,11 +2404,11 @@ if auth_status == True: # # print(summary_df_sorted['Old_sales']) # # print(col, "old efficiency ", a) with bin_placeholder: - if a> 1: + if a > 1.2: fill_color_box = "#6bbf6b" - elif a <1: + elif a <= 1.2: fill_color_box = "#ff6868" - else: + else: fill_color_box = "#ff6868" st.markdown( f""" @@ -2096,7 +2419,7 @@ if auth_status == True: text-align: center; color: {'black'}; "> -

Simulated Efficiency: {round(a,2)}
Actual Efficiency: {round(b,2)}

+

Simulated ROI: {round(a,2)}
Actual ROI: {round(b,2)}

""", @@ -2117,17 +2440,17 @@ if auth_status == True: summary_df_sorted = summary_df.sort_values(by="Delta", ascending=False) summary_df_sorted["Delta_percent"] = np.round( - ((summary_df_sorted["Optimized_spend"] / summary_df_sorted["Actual_spend"]) - 1) + ( + ( + summary_df_sorted["Optimized_spend"] + / summary_df_sorted["Actual_spend"] + ) + - 1 + ) * 100, 2, ) - - - - - - with open("summary_df.pkl", "wb") as f: pickle.dump(summary_df_sorted, f) # st.dataframe(summary_df_sorted) @@ -2144,145 +2467,132 @@ if auth_status == True: scenario_planner_plots() - with st.expander ("View Forecasted spends"): - # st.write("Select Time Period") - - options = ["Next Month","Next Quarter","Next Year","Custom Time Period"] - - # # Create the radio button - forecast_btn_op = st.radio("Select Time Period", options) - - - # List of 12 months - months_start = ["January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December"] - years_start = range(2022,2025) - months_end = ["January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December"] - years_end = range(2022,2025) - - if forecast_btn_op == "Custom Time Period": - col1, col2, col3 = st.columns([1,1,0.75]) - - with col1: - from datetime import date - st.write ("Select Start Time Period") - sc1,sc2 = st.columns([1,1]) - - with sc1: - # Create a dropdown (selectbox) for months - start_date_mon = st.selectbox("Select Start Month:", months_start) - with sc2: - start_date_year = st.selectbox("Select Start Year:", years_start,index=2) - start_date1 = date(start_date_year, months_start.index(start_date_mon)+1, 1) - # - relativedelta(years=1) - # st.write(start_date1) - # default_Month = "January" - # start_date_mon = st.text_input("Select Start Month: ",value=default_Month) - - # default_Year = 2024 - # start_date_year = st.number_input("Select Start Year: ",value=default_Year) - - with col2: - st.write ("Select End Time Period") - ec1,ec2 = st.columns([1,1]) - with ec1: - end_date_mon = st.selectbox("Select End Month:", months_end,index=1) - with ec2: - end_date_year = st.selectbox("Select End Year:", years_end,index=2) - end_date1 = date(end_date_year, months_end.index(end_date_mon)+1, 1)+ relativedelta(months=1) - relativedelta(days=1) - # - relativedelta(years=1) - # st.write(end_date1) - # default_Month = "February" - # end_date_mon = st.text_input("Select End Month: ",value=default_Month) - - # default_Year = 2024 - # end_date_year = st.number_input("Select End Year: ",value=default_Year) - # end_date1 = st.date_input("Select End Date: ",value=default_date) - relativedelta(years=1) - elif forecast_btn_op == 'Next Month': - # current_date = datetime.now() - # start_date1 = current_date- relativedelta(years=1) - # end_date1 = current_date + relativedelta(months=1)- relativedelta(years=1) - start_date1,end_date1 = first_day_of_next_month(datetime.now()) - # start_date1 = start_date1- relativedelta(years=1) - # end_date1 = end_date1 - relativedelta(years=1) - elif forecast_btn_op == 'Next Quarter': - # current_date = datetime.now() - # start_date1 = current_date- relativedelta(years=1) - # end_date1 = current_date + relativedelta(months = 3)- relativedelta(years=1) - start_date1,end_date1 = first_day_of_next_quarter(datetime.now()) - # start_date1 = start_date1- relativedelta(years=1) - # end_date1 = end_date1 - relativedelta(years=1) - elif forecast_btn_op == 'Next Year': - # current_date = datetime.now() - # start_date1 = current_date- relativedelta(years=1) - # end_date1 = current_date + relativedelta(months = 12)- relativedelta(years=1) - start_date1,end_date1 = first_day_of_next_year(datetime.now()) - # start_date1 = start_date1- relativedelta(years=1) - # end_date1 = end_date1 - relativedelta(years=1) - if st.button('Generate Forecasts'): - st.write(f"Forecasted Spends Time Period : {start_date1.strftime('%m-%d-%Y')} to {end_date1.strftime('%m-%d-%Y')}") - if end_date1 < start_date1 : - st.error("End date cannot be less than start date") - forecasted_table_df2 = pd.DataFrame() - try: - - st.write("Forecasted Spends wrt. Channels ") - output_df1, output_df2 = sf.scenario_spend_forecasting(summary_df_sorted,start_date1- relativedelta(years=1),end_date1- relativedelta(years=1)) - forecasted_table_df = output_df1.copy() - # forecasted_table_df.iloc[:2] = forecasted_table_df.iloc[:2].applymap(lambda x: "{:,.0f}".format(x)) - # forecasted_table_df.iloc[-1] = forecasted_table_df.iloc[-1].apply(lambda x: "{:.1f}%".format(x)) - st.dataframe(forecasted_table_df) - - st.write("Monthly Breakdown Of Forecasted Spends wrt. Channels ") - # forecasted_table_df2 = output_df2.applymap(lambda x: "{:,.0f}".format(x)) - st.dataframe(output_df2) - - st.subheader("Download Report") - report_name = st.text_input( - "Report name", - key="report_input", - placeholder="Report name", - label_visibility="collapsed", - ) - st.download_button( - "Download Report", - data = save_report_forecast(output_df1,output_df2), - file_name = report_name+".xlsx", - mime="application/vnd.ms-excel", - # on_click=lambda: save_report_forecast(forecasted_table_df,report_name), - disabled=len(st.session_state["report_input"]) == 0,#use_container_width=True - ) - - except: - st.warning("Please make sure the base data is updated") - - - - - - - - - - - - - # filename = st.text_input("Save Report: ",placeholder="Report name") - # if st.button("Download Report",disabled= (filename != "Report name")): - # excel_file_path = filename+ '.xlsx' - # forecasted_table_df.to_excel(excel_file_path, index=False) - # message_container = st.empty() + # with st.expander ("View Forecasted spends"): + # # st.write("Select Time Period") + + # options = ["Next Month","Next Quarter","Next Year","Custom Time Period"] + + # # # Create the radio button + # forecast_btn_op = st.radio("Select Time Period", options) + + # # List of 12 months + # months_start = ["January", "February", "March", "April", "May", "June", + # "July", "August", "September", "October", "November", "December"] + # years_start = range(2022,2025) + # months_end = ["January", "February", "March", "April", "May", "June", + # "July", "August", "September", "October", "November", "December"] + # years_end = range(2022,2025) + + # if forecast_btn_op == "Custom Time Period": + # col1, col2, col3 = st.columns([1,1,0.75]) + + # with col1: + # from datetime import date + # st.write ("Select Start Time Period") + # sc1,sc2 = st.columns([1,1]) + + # with sc1: + # # Create a dropdown (selectbox) for months + # start_date_mon = st.selectbox("Select Start Month:", months_start) + # with sc2: + # start_date_year = st.selectbox("Select Start Year:", years_start,index=2) + # start_date1 = date(start_date_year, months_start.index(start_date_mon)+1, 1) + # # - relativedelta(years=1) + # # st.write(start_date1) + # # default_Month = "January" + # # start_date_mon = st.text_input("Select Start Month: ",value=default_Month) + + # # default_Year = 2024 + # # start_date_year = st.number_input("Select Start Year: ",value=default_Year) + + # with col2: + # st.write ("Select End Time Period") + # ec1,ec2 = st.columns([1,1]) + # with ec1: + # end_date_mon = st.selectbox("Select End Month:", months_end,index=1) + # with ec2: + # end_date_year = st.selectbox("Select End Year:", years_end,index=2) + # end_date1 = date(end_date_year, months_end.index(end_date_mon)+1, 1)+ relativedelta(months=1) - relativedelta(days=1) + # # - relativedelta(years=1) + # # st.write(end_date1) + # # default_Month = "February" + # # end_date_mon = st.text_input("Select End Month: ",value=default_Month) + + # # default_Year = 2024 + # # end_date_year = st.number_input("Select End Year: ",value=default_Year) + # # end_date1 = st.date_input("Select End Date: ",value=default_date) - relativedelta(years=1) + # elif forecast_btn_op == 'Next Month': + # # current_date = datetime.now() + # # start_date1 = current_date- relativedelta(years=1) + # # end_date1 = current_date + relativedelta(months=1)- relativedelta(years=1) + # start_date1,end_date1 = first_day_of_next_month(datetime.now()) + # # start_date1 = start_date1- relativedelta(years=1) + # # end_date1 = end_date1 - relativedelta(years=1) + # elif forecast_btn_op == 'Next Quarter': + # # current_date = datetime.now() + # # start_date1 = current_date- relativedelta(years=1) + # # end_date1 = current_date + relativedelta(months = 3)- relativedelta(years=1) + # start_date1,end_date1 = first_day_of_next_quarter(datetime.now()) + # # start_date1 = start_date1- relativedelta(years=1) + # # end_date1 = end_date1 - relativedelta(years=1) + # elif forecast_btn_op == 'Next Year': + # # current_date = datetime.now() + # # start_date1 = current_date- relativedelta(years=1) + # # end_date1 = current_date + relativedelta(months = 12)- relativedelta(years=1) + # start_date1,end_date1 = first_day_of_next_year(datetime.now()) + # # start_date1 = start_date1- relativedelta(years=1) + # # end_date1 = end_date1 - relativedelta(years=1) + # if st.button('Generate Forecasts'): + # st.write(f"Forecasted Spends Time Period : {start_date1.strftime('%m-%d-%Y')} to {end_date1.strftime('%m-%d-%Y')}") + # if end_date1 < start_date1 : + # st.error("End date cannot be less than start date") + # forecasted_table_df2 = pd.DataFrame() + # try: + + # st.write("Forecasted Spends wrt. Channels ") + # output_df1, output_df2 = sf.scenario_spend_forecasting(summary_df_sorted,start_date1- relativedelta(years=1),end_date1- relativedelta(years=1)) + # forecasted_table_df = output_df1.copy() + # # forecasted_table_df.iloc[:2] = forecasted_table_df.iloc[:2].applymap(lambda x: "{:,.0f}".format(x)) + # # forecasted_table_df.iloc[-1] = forecasted_table_df.iloc[-1].apply(lambda x: "{:.1f}%".format(x)) + # st.dataframe(forecasted_table_df) + + # st.write("Monthly Breakdown Of Forecasted Spends wrt. Channels ") + # # forecasted_table_df2 = output_df2.applymap(lambda x: "{:,.0f}".format(x)) + # st.dataframe(output_df2) + + # st.subheader("Download Report") + # report_name = st.text_input( + # "Report name", + # key="report_input", + # placeholder="Report name", + # label_visibility="collapsed", + # ) + # st.download_button( + # "Download Report", + # data = save_report_forecast(output_df1,output_df2), + # file_name = report_name+".xlsx", + # mime="application/vnd.ms-excel", + # # on_click=lambda: save_report_forecast(forecasted_table_df,report_name), + # disabled=len(st.session_state["report_input"]) == 0,#use_container_width=True + # ) + + # except: + # st.warning("Please make sure the base data is updated") + + # # filename = st.text_input("Save Report: ",placeholder="Report name") + # # if st.button("Download Report",disabled= (filename != "Report name")): + # # excel_file_path = filename+ '.xlsx' + # # forecasted_table_df.to_excel(excel_file_path, index=False) + # # message_container = st.empty() + + # # with message_container: + # # st.write(f'
{"Report Saved!"}
', unsafe_allow_html=True) + # # time.sleep(0.5) + # # st.empty() + + # # on_click=lambda: save_scenario(scenario_name), + # # disabled=len(st.session_state["scenario_input"]) == 0,#use_container_width=True - - # with message_container: - # st.write(f'
{"Report Saved!"}
', unsafe_allow_html=True) - # time.sleep(0.5) - # st.empty() - - # on_click=lambda: save_scenario(scenario_name), - # disabled=len(st.session_state["scenario_input"]) == 0,#use_container_width=True - _columns = st.columns(2) # with _columns[0]: st.subheader("Save Scenario") @@ -2295,8 +2605,8 @@ if auth_status == True: st.button( "Save", on_click=lambda: save_scenario(scenario_name), - disabled=len(st.session_state["scenario_input"]) == 0,#use_container_width=True - + disabled=len(st.session_state["scenario_input"]) + == 0, # use_container_width=True ) # def prepare_download_func(): @@ -2305,8 +2615,8 @@ if auth_status == True: # ppt_file = save_ppt_file(summary_df_sorted,fig1,fig2,fig3) if st.button("Prepare Analysis Download"): - fig1,fig2,fig3 = scenario_planner_plots2() - ppt_file = save_ppt_file(summary_df_sorted,fig1,fig2,fig3) + fig1, fig2, fig3 = scenario_planner_plots2() + ppt_file = save_ppt_file(summary_df_sorted, fig1, fig2, fig3) # Add a download button try: # ppt_file = prepare_download_func() @@ -2326,30 +2636,24 @@ if auth_status == True: # file_name="MMM_Model_Quality_Presentation.pptx", # mime="application/vnd.openxmlformats-officedocument.presentationml.presentation" # ) - - - - elif auth_status == False: - st.error("Username/Password is incorrect") + st.error("Username/Password is incorrect") if auth_status != True: try: username_forgot_pw, email_forgot_password, random_password = ( - authenticator.forgot_password("Forgot password") - ) + authenticator.forgot_password("Forgot password") + ) if username_forgot_pw: - st.session_state["config"]["credentials"]["usernames"][username_forgot_pw][ - "password" - ] = stauth.Hasher([random_password]).generate()[0] - send_email(email_forgot_password, random_password) - st.success("New password sent securely") - # Random password to be transferred to user securely + st.session_state["config"]["credentials"]["usernames"][username_forgot_pw][ + "password" + ] = stauth.Hasher([random_password]).generate()[0] + send_email(email_forgot_password, random_password) + st.success("New password sent securely") + # Random password to be transferred to user securely elif username_forgot_pw == False: - st.error("Username not found") + st.error("Username not found") except Exception as e: st.error(e) - - \ No newline at end of file