Spaces:
Sleeping
Sleeping
Pragya Jatav
commited on
Commit
·
2d928fb
1
Parent(s):
4bae411
m1
Browse files- Streamlit_functions.py +80 -19
- __pycache__/Streamlit_functions.cpython-310.pyc +0 -0
- __pycache__/classes.cpython-310.pyc +0 -0
- __pycache__/response_curves_model_quality.cpython-310.pyc +0 -0
- __pycache__/response_curves_model_quality_base.cpython-310.pyc +0 -0
- __pycache__/utilities.cpython-310.pyc +0 -0
- classes.py +112 -6
- pages/2_Scenario_Planner.py +201 -359
- pages/3_Saved_Scenarios.py +4 -2
- response_curves_model_quality.py +14 -14
- response_curves_model_quality_base.py +53 -17
- summary_df.pkl +1 -1
- utilities.py +20 -220
Streamlit_functions.py
CHANGED
@@ -281,7 +281,7 @@ def waterfall(start_date,end_date,btn_chart):
|
|
281 |
# Updating layout for black background and gray gridlines
|
282 |
if btn_chart == "Month on Month":
|
283 |
fig.update_layout(
|
284 |
-
title=f"Change In MMM Estimated Prospect Contribution
|
285 |
,showlegend=False,
|
286 |
# plot_bgcolor='black',
|
287 |
# paper_bgcolor='black',
|
@@ -293,11 +293,22 @@ def waterfall(start_date,end_date,btn_chart):
|
|
293 |
yaxis=dict(
|
294 |
title="Prospects",
|
295 |
showgrid=True,
|
296 |
-
gridcolor='
|
|
|
297 |
zeroline=False, # Hiding the y-axis zero line
|
298 |
# range=[18000, max(max(cumulative), max(values)) + 1000] # Setting the y-axis range from 19k to slightly above the maximum value
|
299 |
)
|
300 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
# fig.update_xaxes(
|
302 |
# tickmode="array",
|
303 |
# # categoryorder="total ascending",
|
@@ -308,7 +319,7 @@ def waterfall(start_date,end_date,btn_chart):
|
|
308 |
# )
|
309 |
else :
|
310 |
fig.update_layout(
|
311 |
-
title=
|
312 |
,showlegend=False,
|
313 |
# plot_bgcolor='black',
|
314 |
# paper_bgcolor='black',
|
@@ -320,12 +331,23 @@ def waterfall(start_date,end_date,btn_chart):
|
|
320 |
yaxis=dict(
|
321 |
title="Prospects",
|
322 |
showgrid=True,
|
323 |
-
gridcolor='
|
|
|
324 |
zeroline=False, # Hiding the y-axis zero line
|
325 |
# range=[10000, max(cumulative)+1000] # Setting the y-axis range from 19k to slightly above the maximum value
|
326 |
)
|
327 |
|
328 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
329 |
# print(cur_data)
|
330 |
# print(prev_data)
|
331 |
# fig.show()
|
@@ -431,7 +453,7 @@ def channel_contribution(start_date,end_date):
|
|
431 |
|
432 |
# Updating layout for better visualization
|
433 |
fig.update_layout(
|
434 |
-
title=f"Media Contribution
|
435 |
# plot_bgcolor='black',
|
436 |
# paper_bgcolor='black',
|
437 |
# font=dict(color='white'), # Changing font color to white for better contrast
|
@@ -443,10 +465,21 @@ def channel_contribution(start_date,end_date):
|
|
443 |
yaxis=dict(
|
444 |
title="Prospect",
|
445 |
showgrid=True,
|
446 |
-
gridcolor='
|
|
|
447 |
zeroline=False, # Hiding the y-axis zero line
|
448 |
)
|
449 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
450 |
|
451 |
return fig
|
452 |
|
@@ -478,7 +511,7 @@ def chanel_spends(start_date,end_date):
|
|
478 |
|
479 |
# Updating layout for better visualization
|
480 |
fig.update_layout(
|
481 |
-
title=f"Media Spends
|
482 |
# plot_bgcolor='black',
|
483 |
# paper_bgcolor='black',
|
484 |
# font=dict(color='white'), # Changing font color to white for better contrast
|
@@ -490,10 +523,21 @@ def chanel_spends(start_date,end_date):
|
|
490 |
yaxis=dict(
|
491 |
title="Spends ($)",
|
492 |
showgrid=True,
|
493 |
-
gridcolor='
|
|
|
494 |
zeroline=False, # Hiding the y-axis zero line
|
495 |
)
|
496 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
497 |
|
498 |
return fig
|
499 |
|
@@ -590,24 +634,36 @@ def cpp(start_date,end_date):
|
|
590 |
|
591 |
# Update layout for better visualization
|
592 |
fig.update_layout(
|
593 |
-
title=f"CPP Distribution
|
594 |
,
|
595 |
# plot_bgcolor='black',
|
596 |
# paper_bgcolor='black',
|
597 |
# font=dict(color='white'), # Changing font color to white for better contrast
|
598 |
xaxis=dict(
|
599 |
-
showgrid=
|
600 |
-
gridcolor='
|
|
|
601 |
zeroline=False, # Hiding the x-axis zero line
|
602 |
),
|
603 |
yaxis=dict(
|
604 |
title="CPP",
|
605 |
showgrid=True,
|
606 |
-
gridcolor='
|
|
|
607 |
zeroline=False, # Hiding the y-axis zero line
|
608 |
),
|
609 |
hovermode='x' # Show hover info for all lines at a single point
|
610 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
611 |
return fig
|
612 |
|
613 |
def base_decomp():
|
@@ -641,7 +697,8 @@ def base_decomp():
|
|
641 |
yaxis=dict(
|
642 |
title="Prospect",
|
643 |
showgrid=True,
|
644 |
-
gridcolor='
|
|
|
645 |
zeroline=False, # Hiding the y-axis zero line
|
646 |
),
|
647 |
hovermode='x' # Show hover info for all lines at a single point
|
@@ -731,7 +788,8 @@ def media_decomp():
|
|
731 |
yaxis=dict(
|
732 |
title="Prospect",
|
733 |
showgrid=True,
|
734 |
-
gridcolor='
|
|
|
735 |
zeroline=False, # Hiding the y-axis zero line
|
736 |
)
|
737 |
)
|
@@ -749,7 +807,7 @@ def mmm_model_quality():
|
|
749 |
|
750 |
# Update layout for better visualization
|
751 |
fig.update_layout(
|
752 |
-
title=f"Model Predicted
|
753 |
,
|
754 |
# plot_bgcolor='black',
|
755 |
# paper_bgcolor='black',
|
@@ -762,7 +820,8 @@ def mmm_model_quality():
|
|
762 |
yaxis=dict(
|
763 |
title="Prospects",
|
764 |
showgrid=True,
|
765 |
-
gridcolor='
|
|
|
766 |
zeroline=False, # Hiding the y-axis zero line
|
767 |
),
|
768 |
hovermode='x' # Show hover info for all lines at a single point
|
@@ -819,7 +878,8 @@ def elasticity(media_df):
|
|
819 |
xaxis=dict(
|
820 |
title="Elasticity (coefficient)",
|
821 |
showgrid=True,
|
822 |
-
gridcolor='
|
|
|
823 |
zeroline=False, # Hiding the x-axis zero line
|
824 |
),
|
825 |
yaxis=dict(
|
@@ -858,7 +918,8 @@ def half_life(media_df):
|
|
858 |
xaxis=dict(
|
859 |
title="Weeks",
|
860 |
showgrid=True,
|
861 |
-
gridcolor='
|
|
|
862 |
zeroline=False, # Hiding the x-axis zero line
|
863 |
),
|
864 |
yaxis=dict(
|
@@ -1024,7 +1085,7 @@ def scenario_spend_forecasting2(delta_df,start_date,end_date):
|
|
1024 |
cur_data = cur_data[spend_cols2]
|
1025 |
cur_data.columns = channels2
|
1026 |
|
1027 |
-
cur_data["Date2"] = cur_data["Date"]+ pd.Timedelta(days=
|
1028 |
# cur_data["Date"] = delta_df["Date"]
|
1029 |
cur_data["Date_diff"] = (cur_data["Date"]-start_date).dt.days
|
1030 |
cur_data["Date_diff_months"] =(np.ceil(cur_data["Date_diff"] / 30))
|
|
|
281 |
# Updating layout for black background and gray gridlines
|
282 |
if btn_chart == "Month on Month":
|
283 |
fig.update_layout(
|
284 |
+
title=f"Change In MMM Estimated Prospect Contribution"
|
285 |
,showlegend=False,
|
286 |
# plot_bgcolor='black',
|
287 |
# paper_bgcolor='black',
|
|
|
293 |
yaxis=dict(
|
294 |
title="Prospects",
|
295 |
showgrid=True,
|
296 |
+
gridcolor='lightgray',
|
297 |
+
griddash='dot', # Setting y-axis gridline color to gray
|
298 |
zeroline=False, # Hiding the y-axis zero line
|
299 |
# range=[18000, max(max(cumulative), max(values)) + 1000] # Setting the y-axis range from 19k to slightly above the maximum value
|
300 |
)
|
301 |
)
|
302 |
+
fig.add_annotation(
|
303 |
+
text=f"{start_date_prev.strftime('%m-%d-%Y')} to {end_date_prev.strftime('%m-%d-%Y')} vs. {start_date.strftime('%m-%d-%Y')} To {end_date.strftime('%m-%d-%Y')}",
|
304 |
+
x=0,
|
305 |
+
y=1.15,
|
306 |
+
xref="x domain",
|
307 |
+
yref="y domain",
|
308 |
+
showarrow=False,
|
309 |
+
font=dict(size=16),
|
310 |
+
# align='left'
|
311 |
+
)
|
312 |
# fig.update_xaxes(
|
313 |
# tickmode="array",
|
314 |
# # categoryorder="total ascending",
|
|
|
319 |
# )
|
320 |
else :
|
321 |
fig.update_layout(
|
322 |
+
title="Change In MMM Estimated Prospect Contribution "
|
323 |
,showlegend=False,
|
324 |
# plot_bgcolor='black',
|
325 |
# paper_bgcolor='black',
|
|
|
331 |
yaxis=dict(
|
332 |
title="Prospects",
|
333 |
showgrid=True,
|
334 |
+
gridcolor='lightgray',
|
335 |
+
griddash='dot', # Setting y-axis gridline color to gray
|
336 |
zeroline=False, # Hiding the y-axis zero line
|
337 |
# range=[10000, max(cumulative)+1000] # Setting the y-axis range from 19k to slightly above the maximum value
|
338 |
)
|
339 |
|
340 |
)
|
341 |
+
fig.add_annotation(
|
342 |
+
text=f"{start_date_prev.strftime('%m-%d-%Y')} to {end_date_prev.strftime('%m-%d-%Y')} vs. {start_date.strftime('%m-%d-%Y')} To {end_date.strftime('%m-%d-%Y')}",
|
343 |
+
x=0,
|
344 |
+
y=1.15,
|
345 |
+
xref="x domain",
|
346 |
+
yref="y domain",
|
347 |
+
showarrow=False,
|
348 |
+
font=dict(size=16),
|
349 |
+
# align='left'
|
350 |
+
)
|
351 |
# print(cur_data)
|
352 |
# print(prev_data)
|
353 |
# fig.show()
|
|
|
453 |
|
454 |
# Updating layout for better visualization
|
455 |
fig.update_layout(
|
456 |
+
title=f"Media Contribution",
|
457 |
# plot_bgcolor='black',
|
458 |
# paper_bgcolor='black',
|
459 |
# font=dict(color='white'), # Changing font color to white for better contrast
|
|
|
465 |
yaxis=dict(
|
466 |
title="Prospect",
|
467 |
showgrid=True,
|
468 |
+
gridcolor='lightgray',
|
469 |
+
griddash='dot', # Setting y-axis gridline color to gray
|
470 |
zeroline=False, # Hiding the y-axis zero line
|
471 |
)
|
472 |
)
|
473 |
+
fig.add_annotation(
|
474 |
+
text=f"{cur_data['Date'].min().strftime('%m-%d-%Y')} to {cur_data['Date'].max().strftime('%m-%d-%Y')}",
|
475 |
+
x=0,
|
476 |
+
y=1.15,
|
477 |
+
xref="x domain",
|
478 |
+
yref="y domain",
|
479 |
+
showarrow=False,
|
480 |
+
font=dict(size=16),
|
481 |
+
# align='left'
|
482 |
+
)
|
483 |
|
484 |
return fig
|
485 |
|
|
|
511 |
|
512 |
# Updating layout for better visualization
|
513 |
fig.update_layout(
|
514 |
+
title=f"Media Spends",
|
515 |
# plot_bgcolor='black',
|
516 |
# paper_bgcolor='black',
|
517 |
# font=dict(color='white'), # Changing font color to white for better contrast
|
|
|
523 |
yaxis=dict(
|
524 |
title="Spends ($)",
|
525 |
showgrid=True,
|
526 |
+
gridcolor='lightgray',
|
527 |
+
griddash='dot', # Setting y-axis gridline color to gray
|
528 |
zeroline=False, # Hiding the y-axis zero line
|
529 |
)
|
530 |
)
|
531 |
+
fig.add_annotation(
|
532 |
+
text=f"{cur_data['Date'].min().strftime('%m-%d-%Y')} to {cur_data['Date'].max().strftime('%m-%d-%Y')}",
|
533 |
+
x=0,
|
534 |
+
y=1.15,
|
535 |
+
xref="x domain",
|
536 |
+
yref="y domain",
|
537 |
+
showarrow=False,
|
538 |
+
font=dict(size=16),
|
539 |
+
# align='left'
|
540 |
+
)
|
541 |
|
542 |
return fig
|
543 |
|
|
|
634 |
|
635 |
# Update layout for better visualization
|
636 |
fig.update_layout(
|
637 |
+
title=f"CPP Distribution"
|
638 |
,
|
639 |
# plot_bgcolor='black',
|
640 |
# paper_bgcolor='black',
|
641 |
# font=dict(color='white'), # Changing font color to white for better contrast
|
642 |
xaxis=dict(
|
643 |
+
showgrid=False,
|
644 |
+
gridcolor='lightgray',
|
645 |
+
griddash='dot', # Setting x-axis gridline color to gray
|
646 |
zeroline=False, # Hiding the x-axis zero line
|
647 |
),
|
648 |
yaxis=dict(
|
649 |
title="CPP",
|
650 |
showgrid=True,
|
651 |
+
gridcolor='lightgray',
|
652 |
+
griddash='dot', # Setting y-axis gridline color to gray
|
653 |
zeroline=False, # Hiding the y-axis zero line
|
654 |
),
|
655 |
hovermode='x' # Show hover info for all lines at a single point
|
656 |
)
|
657 |
+
fig.add_annotation(
|
658 |
+
text=f"{cur_data['Date'].min().strftime('%m-%d-%Y')} to {cur_data['Date'].max().strftime('%m-%d-%Y')}",
|
659 |
+
x=0,
|
660 |
+
y=1.15,
|
661 |
+
xref="x domain",
|
662 |
+
yref="y domain",
|
663 |
+
showarrow=False,
|
664 |
+
font=dict(size=16),
|
665 |
+
# align='left'
|
666 |
+
)
|
667 |
return fig
|
668 |
|
669 |
def base_decomp():
|
|
|
697 |
yaxis=dict(
|
698 |
title="Prospect",
|
699 |
showgrid=True,
|
700 |
+
gridcolor='lightgray',
|
701 |
+
griddash='dot', # Setting y-axis gridline color to gray
|
702 |
zeroline=False, # Hiding the y-axis zero line
|
703 |
),
|
704 |
hovermode='x' # Show hover info for all lines at a single point
|
|
|
788 |
yaxis=dict(
|
789 |
title="Prospect",
|
790 |
showgrid=True,
|
791 |
+
gridcolor='lightgray',
|
792 |
+
griddash='dot', # Setting y-axis gridline color to gray
|
793 |
zeroline=False, # Hiding the y-axis zero line
|
794 |
)
|
795 |
)
|
|
|
807 |
|
808 |
# Update layout for better visualization
|
809 |
fig.update_layout(
|
810 |
+
title=f"Model Predicted v/s Actual Prospects"
|
811 |
,
|
812 |
# plot_bgcolor='black',
|
813 |
# paper_bgcolor='black',
|
|
|
820 |
yaxis=dict(
|
821 |
title="Prospects",
|
822 |
showgrid=True,
|
823 |
+
gridcolor='lightgray',
|
824 |
+
griddash='dot', # Setting y-axis gridline color to gray
|
825 |
zeroline=False, # Hiding the y-axis zero line
|
826 |
),
|
827 |
hovermode='x' # Show hover info for all lines at a single point
|
|
|
878 |
xaxis=dict(
|
879 |
title="Elasticity (coefficient)",
|
880 |
showgrid=True,
|
881 |
+
gridcolor='lightgray',
|
882 |
+
griddash='dot', # Setting x-axis gridline color to gray
|
883 |
zeroline=False, # Hiding the x-axis zero line
|
884 |
),
|
885 |
yaxis=dict(
|
|
|
918 |
xaxis=dict(
|
919 |
title="Weeks",
|
920 |
showgrid=True,
|
921 |
+
gridcolor='lightgray',
|
922 |
+
griddash='dot', # Setting x-axis gridline color to gray
|
923 |
zeroline=False, # Hiding the x-axis zero line
|
924 |
),
|
925 |
yaxis=dict(
|
|
|
1085 |
cur_data = cur_data[spend_cols2]
|
1086 |
cur_data.columns = channels2
|
1087 |
|
1088 |
+
cur_data["Date2"] = cur_data["Date"]+ pd.Timedelta(days=6)
|
1089 |
# cur_data["Date"] = delta_df["Date"]
|
1090 |
cur_data["Date_diff"] = (cur_data["Date"]-start_date).dt.days
|
1091 |
cur_data["Date_diff_months"] =(np.ceil(cur_data["Date_diff"] / 30))
|
__pycache__/Streamlit_functions.cpython-310.pyc
CHANGED
Binary files a/__pycache__/Streamlit_functions.cpython-310.pyc and b/__pycache__/Streamlit_functions.cpython-310.pyc differ
|
|
__pycache__/classes.cpython-310.pyc
CHANGED
Binary files a/__pycache__/classes.cpython-310.pyc and b/__pycache__/classes.cpython-310.pyc differ
|
|
__pycache__/response_curves_model_quality.cpython-310.pyc
CHANGED
Binary files a/__pycache__/response_curves_model_quality.cpython-310.pyc and b/__pycache__/response_curves_model_quality.cpython-310.pyc differ
|
|
__pycache__/response_curves_model_quality_base.cpython-310.pyc
CHANGED
Binary files a/__pycache__/response_curves_model_quality_base.cpython-310.pyc and b/__pycache__/response_curves_model_quality_base.cpython-310.pyc differ
|
|
__pycache__/utilities.cpython-310.pyc
CHANGED
Binary files a/__pycache__/utilities.cpython-310.pyc and b/__pycache__/utilities.cpython-310.pyc differ
|
|
classes.py
CHANGED
@@ -3,7 +3,7 @@ from scipy.optimize import minimize, LinearConstraint, NonlinearConstraint
|
|
3 |
from collections import OrderedDict
|
4 |
import pandas as pd
|
5 |
from numerize.numerize import numerize
|
6 |
-
|
7 |
|
8 |
def class_to_dict(class_instance):
|
9 |
attr_dict = {}
|
@@ -23,8 +23,8 @@ def class_to_dict(class_instance):
|
|
23 |
attr_dict["actual_total_sales"] = class_instance.actual_total_sales
|
24 |
attr_dict["modified_total_spends"] = class_instance.modified_total_spends
|
25 |
attr_dict["modified_total_sales"] = class_instance.modified_total_sales
|
26 |
-
attr_dict["actual_mroi"] = class_instance.get_marginal_roi("actual")
|
27 |
-
attr_dict["modified_mroi"] = class_instance.get_marginal_roi("modified")
|
28 |
|
29 |
elif isinstance(class_instance, Scenario):
|
30 |
attr_dict["type"] = "Scenario"
|
@@ -56,6 +56,7 @@ class Channel:
|
|
56 |
name,
|
57 |
dates,
|
58 |
spends,
|
|
|
59 |
response_curve_type,
|
60 |
response_curve_params,
|
61 |
bounds,channel_bounds_min,channel_bounds_max,
|
@@ -67,6 +68,7 @@ class Channel:
|
|
67 |
self.dates = dates
|
68 |
self.conversion_rate = conversion_rate
|
69 |
self.actual_spends = spends.copy()
|
|
|
70 |
|
71 |
if modified_spends is None:
|
72 |
self.modified_spends = self.actual_spends.copy()
|
@@ -83,7 +85,7 @@ class Channel:
|
|
83 |
self.upper_limit = self.actual_spends.max() + self.actual_spends.std()
|
84 |
self.power = np.ceil(np.log(self.actual_spends.max()) / np.log(10)) - 3
|
85 |
self.actual_sales = None
|
86 |
-
self.actual_sales = self.response_curve(self.actual_spends)
|
87 |
self.actual_total_spends = self.actual_spends.sum()
|
88 |
self.actual_total_sales = self.actual_sales.sum()
|
89 |
self.modified_sales = self.calculate_sales()
|
@@ -104,8 +106,11 @@ class Channel:
|
|
104 |
)
|
105 |
|
106 |
def calculate_sales(self):
|
|
|
107 |
return self.response_curve(self.modified_spends)
|
108 |
|
|
|
|
|
109 |
def response_curve(self, x):
|
110 |
if self.penalty:
|
111 |
x = np.where(
|
@@ -113,11 +118,33 @@ class Channel:
|
|
113 |
x,
|
114 |
self.upper_limit + (x - self.upper_limit) * self.upper_limit / x,
|
115 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
if self.response_curve_type == "s-curve":
|
117 |
if self.power >= 0:
|
118 |
x = x / 10**self.power
|
119 |
x = x.astype("float64")
|
120 |
-
K = self.response_curve_params["
|
121 |
b = self.response_curve_params["b"]
|
122 |
a = self.response_curve_params["a"]
|
123 |
x0 = self.response_curve_params["x0"]
|
@@ -247,7 +274,7 @@ class Scenario:
|
|
247 |
|
248 |
def update_bounds_min(self, channel_name,modified_bound):
|
249 |
# self.modify_spends(total_spends)
|
250 |
-
self.channels[channel_name].update_bounds_min(modified_bound)
|
251 |
|
252 |
def update_bounds_max(self, channel_name,modified_bound):
|
253 |
# self.modify_spends(total_spends)
|
@@ -290,6 +317,20 @@ class Scenario:
|
|
290 |
|
291 |
# return zip(channels_list, res.x)
|
292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
def optimize_spends(self, sales_percent, channels_list, algo="trust-constr"):
|
294 |
print("%"*100)
|
295 |
desired_sales = self.actual_total_sales * (1 + sales_percent / 100.0)
|
@@ -327,6 +368,8 @@ class Scenario:
|
|
327 |
self.update(channel_name, modified_spends)
|
328 |
|
329 |
return zip(channels_list, res.x)
|
|
|
|
|
330 |
|
331 |
def optimize(self, spends_percent, channels_list):
|
332 |
# channels_list = self.channels.keys()
|
@@ -386,6 +429,69 @@ class Scenario:
|
|
386 |
self.update(channel_name, modified_spends)
|
387 |
|
388 |
return zip(channels_list, res.x)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
389 |
|
390 |
def save(self):
|
391 |
details = {}
|
|
|
3 |
from collections import OrderedDict
|
4 |
import pandas as pd
|
5 |
from numerize.numerize import numerize
|
6 |
+
from gekko import GEKKO
|
7 |
|
8 |
def class_to_dict(class_instance):
|
9 |
attr_dict = {}
|
|
|
23 |
attr_dict["actual_total_sales"] = class_instance.actual_total_sales
|
24 |
attr_dict["modified_total_spends"] = class_instance.modified_total_spends
|
25 |
attr_dict["modified_total_sales"] = class_instance.modified_total_sales
|
26 |
+
# attr_dict["actual_mroi"] = class_instance.get_marginal_roi("actual")
|
27 |
+
# attr_dict["modified_mroi"] = class_instance.get_marginal_roi("modified")
|
28 |
|
29 |
elif isinstance(class_instance, Scenario):
|
30 |
attr_dict["type"] = "Scenario"
|
|
|
56 |
name,
|
57 |
dates,
|
58 |
spends,
|
59 |
+
sales,
|
60 |
response_curve_type,
|
61 |
response_curve_params,
|
62 |
bounds,channel_bounds_min,channel_bounds_max,
|
|
|
68 |
self.dates = dates
|
69 |
self.conversion_rate = conversion_rate
|
70 |
self.actual_spends = spends.copy()
|
71 |
+
# self.actual_sales = sales.copy()
|
72 |
|
73 |
if modified_spends is None:
|
74 |
self.modified_spends = self.actual_spends.copy()
|
|
|
85 |
self.upper_limit = self.actual_spends.max() + self.actual_spends.std()
|
86 |
self.power = np.ceil(np.log(self.actual_spends.max()) / np.log(10)) - 3
|
87 |
self.actual_sales = None
|
88 |
+
self.actual_sales = self.response_curve(self.actual_spends)#sales.copy()#
|
89 |
self.actual_total_spends = self.actual_spends.sum()
|
90 |
self.actual_total_sales = self.actual_sales.sum()
|
91 |
self.modified_sales = self.calculate_sales()
|
|
|
106 |
)
|
107 |
|
108 |
def calculate_sales(self):
|
109 |
+
print("in calc_sales")
|
110 |
return self.response_curve(self.modified_spends)
|
111 |
|
112 |
+
def hill_equation(x, Kd, n):
|
113 |
+
return x**n / (Kd**n + x**n)
|
114 |
def response_curve(self, x):
|
115 |
if self.penalty:
|
116 |
x = np.where(
|
|
|
118 |
x,
|
119 |
self.upper_limit + (x - self.upper_limit) * self.upper_limit / x,
|
120 |
)
|
121 |
+
if self.response_curve_type == "hill-eq":
|
122 |
+
print("lalala")
|
123 |
+
print(self.name)
|
124 |
+
Kd= self.response_curve_params["Kd"]
|
125 |
+
n= self.response_curve_params["n"]
|
126 |
+
x_min= self.response_curve_params["x_min"]
|
127 |
+
x_max= self.response_curve_params["x_max"]
|
128 |
+
y_min= self.response_curve_params["y_min"]
|
129 |
+
y_max= self.response_curve_params['y_max']
|
130 |
+
# print(x_min)
|
131 |
+
# print(Kd,n,x_min,x_max,y_min,y_max)
|
132 |
+
print(np.sum(x)/104)
|
133 |
+
x_inp = ( x- x_min) / (x_max - x_min)
|
134 |
+
# print(x_inp)
|
135 |
+
x_out = x_inp**n / (Kd**n + x_inp**n) #self.hill_equation(x_inp,Kd, n)
|
136 |
+
print(x_out)
|
137 |
+
|
138 |
+
sales = (y_max - y_min)*x_out + y_min
|
139 |
+
sales[np.isnan(sales)] = 0
|
140 |
+
print(sales)
|
141 |
+
print(np.sum(sales))
|
142 |
+
# print(sales)
|
143 |
if self.response_curve_type == "s-curve":
|
144 |
if self.power >= 0:
|
145 |
x = x / 10**self.power
|
146 |
x = x.astype("float64")
|
147 |
+
K = self.response_curve_params["Kd"]
|
148 |
b = self.response_curve_params["b"]
|
149 |
a = self.response_curve_params["a"]
|
150 |
x0 = self.response_curve_params["x0"]
|
|
|
274 |
|
275 |
def update_bounds_min(self, channel_name,modified_bound):
|
276 |
# self.modify_spends(total_spends)
|
277 |
+
self.channels[channel_name].update_bounds_min(modified_bound)
|
278 |
|
279 |
def update_bounds_max(self, channel_name,modified_bound):
|
280 |
# self.modify_spends(total_spends)
|
|
|
317 |
|
318 |
# return zip(channels_list, res.x)
|
319 |
|
320 |
+
def hill_equation(x, Kd, n):
|
321 |
+
return x**n / (Kd**n + x**n)
|
322 |
+
|
323 |
+
def cost_func(channel,x):
|
324 |
+
x_inp = (x/104 - param_dicts["x_min"][channel]) / (param_dicts["x_max"][channel] - param_dicts["x_min"][channel])
|
325 |
+
# print(x_inp)
|
326 |
+
x_out = hill_equation(x_inp, param_dicts["Kd"][channel], param_dicts["n"][channel])
|
327 |
+
# print(x_out)
|
328 |
+
#
|
329 |
+
return (param_dicts["y_max"][channel] - param_dicts["y_min"][channel])*(x_out + param_dicts["y_min"][channel])*104
|
330 |
+
|
331 |
+
|
332 |
+
|
333 |
+
|
334 |
def optimize_spends(self, sales_percent, channels_list, algo="trust-constr"):
|
335 |
print("%"*100)
|
336 |
desired_sales = self.actual_total_sales * (1 + sales_percent / 100.0)
|
|
|
368 |
self.update(channel_name, modified_spends)
|
369 |
|
370 |
return zip(channels_list, res.x)
|
371 |
+
|
372 |
+
|
373 |
|
374 |
def optimize(self, spends_percent, channels_list):
|
375 |
# channels_list = self.channels.keys()
|
|
|
429 |
self.update(channel_name, modified_spends)
|
430 |
|
431 |
return zip(channels_list, res.x)
|
432 |
+
|
433 |
+
|
434 |
+
def hill_equation(self,x, Kd, n):
|
435 |
+
return x**n / (Kd**n + x**n)
|
436 |
+
|
437 |
+
def cost_func(self ,channel,x):
|
438 |
+
|
439 |
+
response_curve_params = pd.read_excel(r"C:\Users\PragyaJatav\Downloads\Untitled Folder 2\simulator uploaded - Copy\Simulator-UOPX\response_curves_parameters.xlsx",index_col = "channel")
|
440 |
+
param_dicts = {col: response_curve_params[col].to_dict() for col in response_curve_params.columns}
|
441 |
+
|
442 |
+
x_inp = (x/104 - param_dicts["x_min"][channel]) / (param_dicts["x_max"][channel] - param_dicts["x_min"][channel])
|
443 |
+
# print(x_inp)
|
444 |
+
x_out = self.hill_equation(x_inp, param_dicts["Kd"][channel], param_dicts["n"][channel])
|
445 |
+
# print(x_out)
|
446 |
+
#
|
447 |
+
return (param_dicts["y_max"][channel] - param_dicts["y_min"][channel])*(x_out + param_dicts["y_min"][channel])*104
|
448 |
+
|
449 |
+
|
450 |
+
def spends_optimisation(self, spends_percent,channels_list):
|
451 |
+
m = GEKKO(remote=False)
|
452 |
+
# Define variables
|
453 |
+
# Initialize 13 variables with specific bounds
|
454 |
+
response_curve_params = pd.read_excel(r"C:\Users\PragyaJatav\Downloads\Untitled Folder 2\simulator uploaded - Copy\Simulator-UOPX\response_curves_parameters.xlsx",index_col = "channel")
|
455 |
+
param_dicts = {col: response_curve_params[col].to_dict() for col in response_curve_params.columns}
|
456 |
+
|
457 |
+
initial_values = list(param_dicts["x_min"].values())
|
458 |
+
current_spends = list(param_dicts["current_spends"].values())
|
459 |
+
lower_bounds = list(param_dicts["x_min"].values())
|
460 |
+
|
461 |
+
num_channels = len(channels_list)
|
462 |
+
|
463 |
+
x_vars=[]
|
464 |
+
x_vars = [m.Var(value=param_dicts["current_spends"][_], lb=param_dicts["x_min"][_]*104, ub=5*param_dicts["current_spends"][_]) for _ in channels_list]
|
465 |
+
print(x_vars)
|
466 |
+
# x_vars,lower_bounds
|
467 |
+
|
468 |
+
# Define the objective function to minimize
|
469 |
+
cost = 0
|
470 |
+
spends = 0
|
471 |
+
i = 0
|
472 |
+
for i,c in enumerate(channels_list):
|
473 |
+
# print(c)
|
474 |
+
# print(x_vars[i])
|
475 |
+
cost = cost + (self.cost_func(c, x_vars[i]))
|
476 |
+
spends = spends +x_vars[i]
|
477 |
+
|
478 |
+
|
479 |
+
m.Maximize(cost)
|
480 |
+
|
481 |
+
# Define constraints
|
482 |
+
m.Equation(spends == sum(current_spends)*(1 + spends_percent / 100))
|
483 |
+
m.Equation(spends <= sum(current_spends)*0.5)
|
484 |
+
m.Equation(spends >= sum(current_spends)*1.5)
|
485 |
+
|
486 |
+
m.solve(disp=True)
|
487 |
+
|
488 |
+
for i, var in enumerate(x_vars):
|
489 |
+
print(f"x{i+1} = {var.value[0]}")
|
490 |
+
|
491 |
+
for channel_name, modified_spends in zip(channels_list, x_vars):
|
492 |
+
self.update(channel_name, modified_spends.value[0])
|
493 |
+
|
494 |
+
return zip(channels_list, x_vars)
|
495 |
|
496 |
def save(self):
|
497 |
details = {}
|
pages/2_Scenario_Planner.py
CHANGED
@@ -62,9 +62,15 @@ def optimize(key, status_placeholder):
|
|
62 |
if key.lower() == "media spends":
|
63 |
with status_placeholder:
|
64 |
with st.spinner("Optimizing"):
|
|
|
|
|
65 |
result = st.session_state["scenario"].optimize(
|
66 |
st.session_state["total_spends_change"], channel_list
|
|
|
|
|
67 |
)
|
|
|
|
|
68 |
# elif key.lower() == "revenue":
|
69 |
else:
|
70 |
with status_placeholder:
|
@@ -565,117 +571,6 @@ def plot_response_curves(summary_df_sorted):
|
|
565 |
with col:
|
566 |
st.plotly_chart(fig, use_container_width=True)
|
567 |
|
568 |
-
# cols = st.columns(3)
|
569 |
-
# for i in range(0, len(channels_list)):
|
570 |
-
|
571 |
-
# col = channels_list[i]
|
572 |
-
# if col == "Panel":
|
573 |
-
# continue
|
574 |
-
# st.write(col)
|
575 |
-
# x_modified = summary_df_sorted["Optimized_spend"][col]/104
|
576 |
-
# y_modified = summary_df_sorted["New_sales"][col]/104
|
577 |
-
# st.plotly_chart(rc.response_curves(col,x_modified,y_modified))
|
578 |
-
|
579 |
-
|
580 |
-
# @st.cache
|
581 |
-
# def plot_response_curves():
|
582 |
-
# cols = 4
|
583 |
-
# rcs = st.session_state["rcs"]
|
584 |
-
# shapes = []
|
585 |
-
# fig = make_subplots(rows=6, cols=cols, subplot_titles=channels_list)
|
586 |
-
# for i in range(0, len(channels_list)):
|
587 |
-
# col = channels_list[i]
|
588 |
-
# x = st.session_state["actual_df"][col].values
|
589 |
-
# spends = x.sum()
|
590 |
-
# power = np.ceil(np.log(x.max()) / np.log(10)) - 3
|
591 |
-
# x = np.linspace(0, 3 * x.max(), 200)
|
592 |
-
|
593 |
-
# K = rcs[col]["K"]
|
594 |
-
# b = rcs[col]["b"]
|
595 |
-
# a = rcs[col]["a"]
|
596 |
-
# x0 = rcs[col]["x0"]
|
597 |
-
|
598 |
-
# y = s_curve(x / 10**power, K, b, a, x0)
|
599 |
-
# roi = y / x
|
600 |
-
# marginal_roi = a * (y) * (1 - y / K)
|
601 |
-
# fig.add_trace(
|
602 |
-
# go.Scatter(
|
603 |
-
# x=52
|
604 |
-
# * x
|
605 |
-
# * st.session_state["scenario"].channels[col].conversion_rate,
|
606 |
-
# y=52 * y,
|
607 |
-
# name=col,
|
608 |
-
# customdata=np.stack((roi, marginal_roi), axis=-1),
|
609 |
-
# hovertemplate="Spend:%{x:$.2s}<br>Sale:%{y:$.2s}<br>ROI:%{customdata[0]:.3f}<br>MROI:%{customdata[1]:.3f}",
|
610 |
-
# ),
|
611 |
-
# row=1 + (i) // cols,
|
612 |
-
# col=i % cols + 1,
|
613 |
-
# )
|
614 |
-
|
615 |
-
# fig.add_trace(
|
616 |
-
# go.Scatter(
|
617 |
-
# x=[
|
618 |
-
# spends
|
619 |
-
# * st.session_state["scenario"]
|
620 |
-
# .channels[col]
|
621 |
-
# .conversion_rate
|
622 |
-
# ],
|
623 |
-
# y=[52 * s_curve(spends / (10**power * 52), K, b, a, x0)],
|
624 |
-
# name=col,
|
625 |
-
# legendgroup=col,
|
626 |
-
# showlegend=False,
|
627 |
-
# marker=dict(color=["black"]),
|
628 |
-
# ),
|
629 |
-
# row=1 + (i) // cols,
|
630 |
-
# col=i % cols + 1,
|
631 |
-
# )
|
632 |
-
|
633 |
-
# shapes.append(
|
634 |
-
# go.layout.Shape(
|
635 |
-
# type="line",
|
636 |
-
# x0=0,
|
637 |
-
# y0=52 * s_curve(spends / (10**power * 52), K, b, a, x0),
|
638 |
-
# x1=spends
|
639 |
-
# * st.session_state["scenario"].channels[col].conversion_rate,
|
640 |
-
# y1=52 * s_curve(spends / (10**power * 52), K, b, a, x0),
|
641 |
-
# line_width=1,
|
642 |
-
# line_dash="dash",
|
643 |
-
# line_color="black",
|
644 |
-
# xref=f"x{i+1}",
|
645 |
-
# yref=f"y{i+1}",
|
646 |
-
# )
|
647 |
-
# )
|
648 |
-
|
649 |
-
# shapes.append(
|
650 |
-
# go.layout.Shape(
|
651 |
-
# type="line",
|
652 |
-
# x0=spends
|
653 |
-
# * st.session_state["scenario"].channels[col].conversion_rate,
|
654 |
-
# y0=0,
|
655 |
-
# x1=spends
|
656 |
-
# * st.session_state["scenario"].channels[col].conversion_rate,
|
657 |
-
# y1=52 * s_curve(spends / (10**power * 52), K, b, a, x0),
|
658 |
-
# line_width=1,
|
659 |
-
# line_dash="dash",
|
660 |
-
# line_color="black",
|
661 |
-
# xref=f"x{i+1}",
|
662 |
-
# yref=f"y{i+1}",
|
663 |
-
# )
|
664 |
-
# )
|
665 |
-
|
666 |
-
# fig.update_layout(
|
667 |
-
# height=1500,
|
668 |
-
# width=1000,
|
669 |
-
# title_text="Response Curves",
|
670 |
-
# showlegend=False,
|
671 |
-
# shapes=shapes,
|
672 |
-
# )
|
673 |
-
# fig.update_annotations(font_size=10)
|
674 |
-
# fig.update_xaxes(title="Spends")
|
675 |
-
# fig.update_yaxes(title=target)
|
676 |
-
# return fig
|
677 |
-
|
678 |
-
|
679 |
# ======================================================== #
|
680 |
# ==================== HTML Components =================== #
|
681 |
# ======================================================== #
|
@@ -683,7 +578,7 @@ def plot_response_curves(summary_df_sorted):
|
|
683 |
|
684 |
def generate_spending_header(heading):
|
685 |
return st.markdown(
|
686 |
-
f"""<
|
687 |
)
|
688 |
|
689 |
|
@@ -776,6 +671,7 @@ def reset_inputs():
|
|
776 |
del st.session_state.total_sales_change_abs_slider
|
777 |
|
778 |
st.session_state["initialized"] = False
|
|
|
779 |
def scenario_planner_plots():
|
780 |
with st.expander('Optimized Spends Overview'):
|
781 |
# if st.button('Refresh'):
|
@@ -818,59 +714,6 @@ def scenario_planner_plots():
|
|
818 |
light_red = 'rgba(250, 110, 10, 0.7)'
|
819 |
light_purple = 'rgba(255, 191, 69, 0.7)'
|
820 |
|
821 |
-
|
822 |
-
# # Create subplots with one row and two columns
|
823 |
-
# fig = make_subplots(rows=3, cols=1, subplot_titles=("Actual vs. Optimized Spend", "Actual vs. Optimized Contribution", "Actual vs. Optimized ROI"))
|
824 |
-
# # Add actual vs optimized spend bars
|
825 |
-
|
826 |
-
|
827 |
-
# fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['Actual_spend'], name='Actual',
|
828 |
-
# text=summary_df_sorted['Actual_spend'].apply(format_number) + ' '+' (' + actual_spend_percentage.round(2).astype(str) + '%)',
|
829 |
-
# marker_color=light_blue, orientation='h'),
|
830 |
-
# row=1,
|
831 |
-
# col=1)
|
832 |
-
|
833 |
-
|
834 |
-
# fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['Optimized_spend'], name='Optimized',
|
835 |
-
# text=summary_df_sorted['Optimized_spend'].apply(format_number) + ' (' + optimized_spend_percentage.round(2).astype(str) + '%)',
|
836 |
-
# marker_color=light_orange,
|
837 |
-
# orientation='h'),
|
838 |
-
# row=1,
|
839 |
-
# col=1)
|
840 |
-
|
841 |
-
# fig.update_xaxes(title_text="Amount", row=1, col=1)
|
842 |
-
|
843 |
-
# # Add actual vs optimized Contribution
|
844 |
-
# fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['New_sales'],
|
845 |
-
# name='Optimized Contribution',text=summary_df_sorted['New_sales'].apply(format_number),
|
846 |
-
# marker_color=light_orange, orientation='h',showlegend=False), row=2, col=1)
|
847 |
-
|
848 |
-
# fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['Old_sales'],
|
849 |
-
# name='Actual Contribution',text=summary_df_sorted['Old_sales'].apply(format_number),
|
850 |
-
# marker_color=light_blue, orientation='h',showlegend=False), row=2, col=1)
|
851 |
-
|
852 |
-
|
853 |
-
# fig.update_xaxes(title_text="Contribution", row=2, col=1)
|
854 |
-
|
855 |
-
# # Add actual vs optimized ROI bars
|
856 |
-
|
857 |
-
# fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['new_roi'],
|
858 |
-
# name='Optimized ROI',text=summary_df_sorted['new_roi'].apply(format_number) ,
|
859 |
-
# marker_color=light_orange, orientation='h',showlegend=False), row=3, col=1)
|
860 |
-
|
861 |
-
# fig.add_trace(go.Bar(y=summary_df_sorted['Channel_name'], x=summary_df_sorted['old_roi'],
|
862 |
-
# name='Actual ROI', text=summary_df_sorted['old_roi'].apply(format_number) ,
|
863 |
-
# marker_color=light_blue, orientation='h',showlegend=False), row=3, col=1)
|
864 |
-
|
865 |
-
# fig.update_xaxes(title_text="ROI", row=3, col=1)
|
866 |
-
|
867 |
-
# # Update layout
|
868 |
-
# fig.update_layout(title_text="Actual vs. Optimized Metrics for Media Channels",
|
869 |
-
# showlegend=True, yaxis=dict(title='Media Channels', autorange="reversed"))
|
870 |
-
|
871 |
-
# st.plotly_chart(fig,use_container_width=True)
|
872 |
-
|
873 |
-
# Create subplots with one row and two columns
|
874 |
fig = go.Figure()
|
875 |
# Add actual vs optimized spend bars
|
876 |
|
@@ -993,17 +836,7 @@ if auth_status == True:
|
|
993 |
# Check if state is initiaized
|
994 |
is_state_initiaized = st.session_state.get("initialized", False)
|
995 |
if not is_state_initiaized or st.session_state["first_time"]:
|
996 |
-
|
997 |
-
if panel_selected == "Total Market":
|
998 |
-
initialize_data(
|
999 |
-
panel=panel_selected,
|
1000 |
-
target_file=file_selected,
|
1001 |
-
updated_rcs=updated_rcs,
|
1002 |
-
metrics=metrics_selected,
|
1003 |
-
)
|
1004 |
-
panel = None
|
1005 |
-
else:
|
1006 |
-
initialize_data(
|
1007 |
panel=panel_selected,
|
1008 |
target_file=file_selected,
|
1009 |
updated_rcs=updated_rcs,
|
@@ -1044,6 +877,7 @@ if auth_status == True:
|
|
1044 |
_scenario.actual_total_spends, 1
|
1045 |
)
|
1046 |
|
|
|
1047 |
if "total_sales_change_abs" not in st.session_state:
|
1048 |
st.session_state["total_sales_change_abs"] = numerize(
|
1049 |
_scenario.actual_total_sales, 1
|
@@ -1065,7 +899,7 @@ if auth_status == True:
|
|
1065 |
if "upper_bound_key" not in st.session_state:
|
1066 |
st.session_state["upper_bound_key"] = 10
|
1067 |
|
1068 |
-
|
1069 |
header_df = pd.DataFrame(index=["Actual","Simulated","Change","Percent Change"],columns=["Spends","Prospects"])
|
1070 |
header_df["Spends"]["Actual"] = format_numbers(_scenario.actual_total_spends)
|
1071 |
header_df["Spends"]["Simulated"] = format_numbers(_scenario.modified_total_spends)
|
@@ -1083,7 +917,7 @@ if auth_status == True:
|
|
1083 |
"""
|
1084 |
<style>
|
1085 |
.custom-text_head {
|
1086 |
-
font-size:
|
1087 |
color: 'blue' ; /* Adjust text color */
|
1088 |
|
1089 |
font-weight: bold;
|
@@ -1111,93 +945,85 @@ if auth_status == True:
|
|
1111 |
|
1112 |
_columns = st.columns((1, 1, 1, 1, 1))
|
1113 |
with _columns[0]:
|
1114 |
-
st.
|
|
|
1115 |
with _columns[1]:
|
1116 |
-
st.
|
|
|
1117 |
with _columns[2]:
|
1118 |
-
st.
|
1119 |
-
|
1120 |
-
if _scenario.delta_spends >= 0:
|
1121 |
st.markdown(
|
1122 |
"""
|
1123 |
<style>
|
1124 |
.custom-text {
|
1125 |
-
|
1126 |
color: #6bbf6b ; /* Adjust text color */
|
1127 |
}
|
1128 |
</style>
|
1129 |
""",
|
1130 |
unsafe_allow_html=True
|
1131 |
)
|
1132 |
-
|
1133 |
st.markdown(
|
1134 |
"""
|
1135 |
<style>
|
1136 |
.custom-text {
|
1137 |
-
|
1138 |
color: #ff6868; /* Adjust text color */
|
1139 |
}
|
1140 |
</style>
|
1141 |
""",
|
1142 |
unsafe_allow_html=True
|
1143 |
)
|
|
|
|
|
1144 |
|
1145 |
-
|
1146 |
# Apply custom styles to text
|
1147 |
-
st.markdown(f'<
|
1148 |
with _columns[4]:
|
1149 |
# Apply custom styles to text
|
1150 |
-
st.markdown(f'<p></hr></p>', unsafe_allow_html=True)
|
1151 |
-
st.markdown(f'<
|
1152 |
-
|
1153 |
-
|
1154 |
st.markdown(
|
1155 |
"""<hr class="spends-child-seperator">""",
|
1156 |
unsafe_allow_html=True,
|
1157 |
)
|
1158 |
_columns = st.columns((1, 1, 1, 1, 1))
|
1159 |
with _columns[0]:
|
1160 |
-
st.header("Prospects")
|
|
|
1161 |
with _columns[1]:
|
1162 |
-
st.
|
|
|
1163 |
with _columns[2]:
|
1164 |
-
st.
|
1165 |
-
|
1166 |
-
|
1167 |
-
|
1168 |
st.markdown(
|
1169 |
"""
|
1170 |
<style>
|
1171 |
.custom-text {
|
1172 |
-
font-size:
|
1173 |
color:#6bbf6b ; /* Adjust text color */
|
1174 |
}
|
1175 |
</style>
|
1176 |
""",
|
1177 |
unsafe_allow_html=True
|
1178 |
)
|
1179 |
-
|
1180 |
-
st.markdown(
|
1181 |
-
|
1182 |
-
<style>
|
1183 |
-
.custom-text {
|
1184 |
-
font-size: 36px; /* Adjust font size */
|
1185 |
-
color: #ff6868; /* Adjust text color */
|
1186 |
-
}
|
1187 |
-
</style>
|
1188 |
-
""",
|
1189 |
-
unsafe_allow_html=True
|
1190 |
-
)
|
1191 |
-
|
1192 |
# Apply custom styles to text
|
1193 |
-
st.markdown(f'<
|
1194 |
# st.markdown(f'<p style="color: red;">{st.metric(label="", value=header_df["Prospects"]["Change"])}</p>', unsafe_allow_html=True)
|
1195 |
# st.markdown(f'<p style="color: red;">{header_df["Prospects"]["Change"]}</p>', unsafe_allow_html=True)
|
1196 |
|
1197 |
with _columns[4]:
|
1198 |
-
st.markdown(f'<p></hr></p>', unsafe_allow_html=True)
|
1199 |
# Apply custom styles to text
|
1200 |
-
st.markdown(f'<
|
1201 |
st.markdown(
|
1202 |
"""<hr class="spends-child-seperator">""",
|
1203 |
unsafe_allow_html=True,
|
@@ -1207,31 +1033,33 @@ if auth_status == True:
|
|
1207 |
ef1 = (_scenario.actual_total_spends/_scenario.actual_total_sales)
|
1208 |
ef2 = (_scenario.modified_total_spends/_scenario.modified_total_sales)
|
1209 |
with _columns[0]:
|
1210 |
-
st.
|
|
|
1211 |
with _columns[1]:
|
1212 |
-
st.
|
|
|
1213 |
with _columns[2]:
|
1214 |
-
st.
|
1215 |
-
|
1216 |
-
|
1217 |
-
|
1218 |
st.markdown(
|
1219 |
"""
|
1220 |
<style>
|
1221 |
.custom-text1 {
|
1222 |
-
font-size:
|
1223 |
color:#6bbf6b ; /* Adjust text color */
|
1224 |
}
|
1225 |
</style>
|
1226 |
""",
|
1227 |
unsafe_allow_html=True
|
1228 |
)
|
1229 |
-
|
1230 |
st.markdown(
|
1231 |
"""
|
1232 |
<style>
|
1233 |
.custom-text1 {
|
1234 |
-
font-size:
|
1235 |
color: #ff6868; /* Adjust text color */
|
1236 |
}
|
1237 |
</style>
|
@@ -1239,19 +1067,19 @@ if auth_status == True:
|
|
1239 |
unsafe_allow_html=True
|
1240 |
)
|
1241 |
|
|
|
|
|
|
|
1242 |
# Apply custom styles to text
|
1243 |
-
st.markdown(f'<
|
1244 |
# st.markdown(f'<p style="color: red;">{st.metric(label="", value=header_df["Prospects"]["Change"])}</p>', unsafe_allow_html=True)
|
1245 |
# st.markdown(f'<p style="color: red;">{header_df["Prospects"]["Change"]}</p>', unsafe_allow_html=True)
|
1246 |
|
1247 |
with _columns[4]:
|
1248 |
-
st.markdown(f'<p></hr></p>', unsafe_allow_html=True)
|
1249 |
# Apply custom styles to text
|
1250 |
-
st.markdown(f'<
|
1251 |
-
st.markdown(
|
1252 |
-
"""<hr class="spends-child-seperator">""",
|
1253 |
-
unsafe_allow_html=True,
|
1254 |
-
)
|
1255 |
|
1256 |
# st.markdown("""<hr class="spends-heading-seperator">""", unsafe_allow_html=True)
|
1257 |
|
@@ -1431,11 +1259,8 @@ if auth_status == True:
|
|
1431 |
# on_change=partial(update_data_bound_max_overall)
|
1432 |
)
|
1433 |
|
1434 |
-
|
1435 |
-
|
1436 |
-
|
1437 |
-
min_value = round(_scenario.actual_total_spends * 0.5)
|
1438 |
-
max_value = round(_scenario.actual_total_spends * 1.5)
|
1439 |
st.session_state["total_spends_change_abs_slider_options"] = [
|
1440 |
numerize(value, 1)
|
1441 |
for value in range(min_value, max_value + 1, int(1e4))
|
@@ -1486,10 +1311,10 @@ if auth_status == True:
|
|
1486 |
# st.write(max_value)
|
1487 |
# for value in range(min_value, max_value + 1, int(100)):
|
1488 |
# st.write(numerize(value, 1))
|
1489 |
-
st.session_state["total_sales_change_abs_slider_options"] = [
|
1490 |
-
|
1491 |
-
|
1492 |
-
]
|
1493 |
|
1494 |
# st.select_slider(
|
1495 |
# "Absolute Slider",
|
@@ -1642,33 +1467,41 @@ if auth_status == True:
|
|
1642 |
st.session_state["acutual_predicted"]["Delta"].append(spends_delta)
|
1643 |
_spend_cols = st.columns(2)
|
1644 |
with _spend_cols[0]:
|
1645 |
-
st.
|
1646 |
-
|
1647 |
-
|
1648 |
-
|
1649 |
-
|
1650 |
-
)
|
1651 |
-
|
1652 |
-
|
1653 |
-
|
1654 |
-
|
1655 |
-
|
1656 |
-
|
1657 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1658 |
with _spend_cols[1]:
|
1659 |
-
st.
|
1660 |
-
|
1661 |
-
|
1662 |
-
|
1663 |
-
|
1664 |
-
)
|
1665 |
-
|
1666 |
-
|
1667 |
-
|
1668 |
-
|
1669 |
-
|
1670 |
-
|
1671 |
-
)
|
|
|
|
|
1672 |
|
1673 |
|
1674 |
with _columns[3]:
|
@@ -1682,33 +1515,40 @@ if auth_status == True:
|
|
1682 |
|
1683 |
_prospect_cols = st.columns(2)
|
1684 |
with _prospect_cols[0]:
|
1685 |
-
st.
|
1686 |
-
|
1687 |
-
|
1688 |
-
|
1689 |
-
|
1690 |
-
|
1691 |
-
|
1692 |
-
|
1693 |
-
|
1694 |
-
|
1695 |
-
|
1696 |
-
|
1697 |
-
|
|
|
|
|
|
|
|
|
1698 |
with _prospect_cols[1]:
|
1699 |
-
st.
|
1700 |
-
|
1701 |
-
|
1702 |
-
|
1703 |
-
|
1704 |
-
|
1705 |
-
|
1706 |
-
|
1707 |
-
|
1708 |
-
|
1709 |
-
|
1710 |
-
|
1711 |
-
|
|
|
|
|
|
|
1712 |
|
1713 |
|
1714 |
|
@@ -1752,77 +1592,77 @@ if auth_status == True:
|
|
1752 |
|
1753 |
updated_rcs_key = f"{metrics_selected}#@{panel_selected}#@{channel_name}"
|
1754 |
|
1755 |
-
if updated_rcs and updated_rcs_key in list(updated_rcs.keys()):
|
1756 |
-
|
1757 |
-
|
1758 |
-
|
1759 |
-
|
1760 |
-
else:
|
1761 |
-
|
1762 |
-
|
1763 |
-
|
1764 |
-
|
1765 |
-
|
1766 |
-
x_plot = np.linspace(0, 5 * x_actual.sum(), 200)
|
1767 |
-
|
1768 |
-
# Append current_channel_spends to the end of x_plot
|
1769 |
-
x_plot = np.append(x_plot, current_channel_spends)
|
1770 |
-
|
1771 |
-
x, y, marginal_roi = [], [], []
|
1772 |
-
for x_p in x_plot:
|
1773 |
-
|
1774 |
-
|
1775 |
-
for index in range(len(x_plot)):
|
1776 |
-
|
1777 |
-
|
1778 |
-
for index in range(len(x_plot)):
|
1779 |
-
|
1780 |
-
|
1781 |
-
|
1782 |
-
|
1783 |
-
x = (
|
1784 |
-
|
1785 |
-
|
1786 |
-
)
|
1787 |
-
y = np.sum(y, axis=1)
|
1788 |
-
marginal_roi = (
|
1789 |
-
|
1790 |
-
|
1791 |
-
)
|
1792 |
|
1793 |
-
roi = y / np.maximum(x, np.finfo(float).eps)
|
1794 |
-
# roi = (y/np.sum(y))/(x/np.sum(x))
|
1795 |
-
# st.write(x)
|
1796 |
-
# st.write(y)
|
1797 |
-
# st.write(roi)
|
1798 |
|
1799 |
-
# st.write(roi[-1])
|
1800 |
|
1801 |
-
roi_current, marginal_roi_current = roi[-1], marginal_roi[-1]
|
1802 |
-
x, y, roi, marginal_roi = (
|
1803 |
-
|
1804 |
-
|
1805 |
-
|
1806 |
-
|
1807 |
-
) # Drop data for current spends
|
1808 |
-
|
1809 |
-
# roi_current =
|
1810 |
-
|
1811 |
-
start_value, end_value, left_value, right_value = find_segment_value(
|
1812 |
-
|
1813 |
-
|
1814 |
-
|
1815 |
-
)
|
1816 |
|
1817 |
#st.write(roi_current)
|
1818 |
|
1819 |
-
rgba = calculate_rgba(
|
1820 |
-
|
1821 |
-
|
1822 |
-
|
1823 |
-
|
1824 |
-
|
1825 |
-
)
|
1826 |
|
1827 |
summary_df = pd.DataFrame(st.session_state["acutual_predicted"])
|
1828 |
# st.dataframe(summary_df)
|
@@ -1860,12 +1700,14 @@ if auth_status == True:
|
|
1860 |
text-align: center;
|
1861 |
color: {'black'};
|
1862 |
">
|
1863 |
-
<p style="margin: 0; font-size:
|
1864 |
-
<!--<p style="margin: 0; font-size:
|
1865 |
</div>
|
1866 |
""",
|
1867 |
unsafe_allow_html=True,
|
1868 |
)
|
|
|
|
|
1869 |
|
1870 |
with st.expander("See Response Curves", expanded=True):
|
1871 |
fig = plot_response_curves(summary_df_sorted)
|
|
|
62 |
if key.lower() == "media spends":
|
63 |
with status_placeholder:
|
64 |
with st.spinner("Optimizing"):
|
65 |
+
print(channel_list)
|
66 |
+
print(st.session_state["total_spends_change"])
|
67 |
result = st.session_state["scenario"].optimize(
|
68 |
st.session_state["total_spends_change"], channel_list
|
69 |
+
# result = st.session_state["scenario"].spends_optimisation(
|
70 |
+
# st.session_state["total_spends_change"], channel_list
|
71 |
)
|
72 |
+
|
73 |
+
|
74 |
# elif key.lower() == "revenue":
|
75 |
else:
|
76 |
with status_placeholder:
|
|
|
571 |
with col:
|
572 |
st.plotly_chart(fig, use_container_width=True)
|
573 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
574 |
# ======================================================== #
|
575 |
# ==================== HTML Components =================== #
|
576 |
# ======================================================== #
|
|
|
578 |
|
579 |
def generate_spending_header(heading):
|
580 |
return st.markdown(
|
581 |
+
f"""<h4 class="spends-header"><bold>{heading}<bold></h4>""", unsafe_allow_html=True
|
582 |
)
|
583 |
|
584 |
|
|
|
671 |
del st.session_state.total_sales_change_abs_slider
|
672 |
|
673 |
st.session_state["initialized"] = False
|
674 |
+
|
675 |
def scenario_planner_plots():
|
676 |
with st.expander('Optimized Spends Overview'):
|
677 |
# if st.button('Refresh'):
|
|
|
714 |
light_red = 'rgba(250, 110, 10, 0.7)'
|
715 |
light_purple = 'rgba(255, 191, 69, 0.7)'
|
716 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
717 |
fig = go.Figure()
|
718 |
# Add actual vs optimized spend bars
|
719 |
|
|
|
836 |
# Check if state is initiaized
|
837 |
is_state_initiaized = st.session_state.get("initialized", False)
|
838 |
if not is_state_initiaized or st.session_state["first_time"]:
|
839 |
+
initialize_data(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
840 |
panel=panel_selected,
|
841 |
target_file=file_selected,
|
842 |
updated_rcs=updated_rcs,
|
|
|
877 |
_scenario.actual_total_spends, 1
|
878 |
)
|
879 |
|
880 |
+
st.write(_scenario.actual_total_sales)
|
881 |
if "total_sales_change_abs" not in st.session_state:
|
882 |
st.session_state["total_sales_change_abs"] = numerize(
|
883 |
_scenario.actual_total_sales, 1
|
|
|
899 |
if "upper_bound_key" not in st.session_state:
|
900 |
st.session_state["upper_bound_key"] = 10
|
901 |
|
902 |
+
st.write(_scenario.modified_total_sales)
|
903 |
header_df = pd.DataFrame(index=["Actual","Simulated","Change","Percent Change"],columns=["Spends","Prospects"])
|
904 |
header_df["Spends"]["Actual"] = format_numbers(_scenario.actual_total_spends)
|
905 |
header_df["Spends"]["Simulated"] = format_numbers(_scenario.modified_total_spends)
|
|
|
917 |
"""
|
918 |
<style>
|
919 |
.custom-text_head {
|
920 |
+
font-size: 24px; /* Adjust font size */
|
921 |
color: 'blue' ; /* Adjust text color */
|
922 |
|
923 |
font-weight: bold;
|
|
|
945 |
|
946 |
_columns = st.columns((1, 1, 1, 1, 1))
|
947 |
with _columns[0]:
|
948 |
+
st.markdown("""<h4> Spends</h4>""",unsafe_allow_html=True)
|
949 |
+
# st.write("Spends")
|
950 |
with _columns[1]:
|
951 |
+
st.markdown(f"""<h4>{header_df["Spends"]["Actual"]}</h4>""",unsafe_allow_html=True)
|
952 |
+
# st.metric(label="", value=header_df["Spends"]["Actual"])
|
953 |
with _columns[2]:
|
954 |
+
st.markdown(f"""<h4>{header_df["Spends"]["Simulated"]}</h4>""",unsafe_allow_html=True)
|
955 |
+
if _scenario.delta_spends < 0:
|
|
|
956 |
st.markdown(
|
957 |
"""
|
958 |
<style>
|
959 |
.custom-text {
|
960 |
+
font-size: 24px; /* Adjust font size */
|
961 |
color: #6bbf6b ; /* Adjust text color */
|
962 |
}
|
963 |
</style>
|
964 |
""",
|
965 |
unsafe_allow_html=True
|
966 |
)
|
967 |
+
else:
|
968 |
st.markdown(
|
969 |
"""
|
970 |
<style>
|
971 |
.custom-text {
|
972 |
+
font-size: 24px; /* Adjust font size */
|
973 |
color: #ff6868; /* Adjust text color */
|
974 |
}
|
975 |
</style>
|
976 |
""",
|
977 |
unsafe_allow_html=True
|
978 |
)
|
979 |
+
# st.metric(label="", value=header_df["Spends"]["Simulated"])
|
980 |
+
with _columns[3]:
|
981 |
|
|
|
982 |
# Apply custom styles to text
|
983 |
+
st.markdown(f'<h4 class="custom-text">{header_df["Spends"]["Change"]}</h4>', unsafe_allow_html=True)
|
984 |
with _columns[4]:
|
985 |
# Apply custom styles to text
|
986 |
+
# st.markdown(f'<p></hr></p>', unsafe_allow_html=True)
|
987 |
+
st.markdown(f'<h4 class="custom-text">{header_df["Spends"]["Percent Change"]}</h4>', unsafe_allow_html=True)
|
|
|
|
|
988 |
st.markdown(
|
989 |
"""<hr class="spends-child-seperator">""",
|
990 |
unsafe_allow_html=True,
|
991 |
)
|
992 |
_columns = st.columns((1, 1, 1, 1, 1))
|
993 |
with _columns[0]:
|
994 |
+
# st.header("Prospects")
|
995 |
+
st.markdown("""<h4> Prospects</h4>""",unsafe_allow_html=True)
|
996 |
with _columns[1]:
|
997 |
+
st.markdown(f"""<h4>{header_df["Prospects"]["Actual"]}</h4>""",unsafe_allow_html=True)
|
998 |
+
# st.metric(label="", value=header_df["Prospects"]["Actual"])
|
999 |
with _columns[2]:
|
1000 |
+
st.markdown(f"""<h4>{header_df["Prospects"]["Simulated"]}</h4>""",unsafe_allow_html=True)
|
1001 |
+
# st.metric(label="", value=header_df["Prospects"]["Simulated"])
|
1002 |
+
|
1003 |
+
if _scenario.delta_sales >= 0:
|
1004 |
st.markdown(
|
1005 |
"""
|
1006 |
<style>
|
1007 |
.custom-text {
|
1008 |
+
font-size: 24px; /* Adjust font size */
|
1009 |
color:#6bbf6b ; /* Adjust text color */
|
1010 |
}
|
1011 |
</style>
|
1012 |
""",
|
1013 |
unsafe_allow_html=True
|
1014 |
)
|
1015 |
+
else:
|
1016 |
+
st.markdown("""<style>.custom-text {font-size: 24px; /* Adjust font size */color: #ff6868; /* Adjust text color */}</style>""",unsafe_allow_html=True)
|
1017 |
+
with _columns[3]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1018 |
# Apply custom styles to text
|
1019 |
+
st.markdown(f'<h4 class="custom-text">{header_df["Prospects"]["Change"]}</h4>', unsafe_allow_html=True)
|
1020 |
# st.markdown(f'<p style="color: red;">{st.metric(label="", value=header_df["Prospects"]["Change"])}</p>', unsafe_allow_html=True)
|
1021 |
# st.markdown(f'<p style="color: red;">{header_df["Prospects"]["Change"]}</p>', unsafe_allow_html=True)
|
1022 |
|
1023 |
with _columns[4]:
|
1024 |
+
# st.markdown(f'<p></hr></p>', unsafe_allow_html=True)
|
1025 |
# Apply custom styles to text
|
1026 |
+
st.markdown(f'<h4 class="custom-text">{header_df["Prospects"]["Percent Change"]}</h4>', unsafe_allow_html=True)
|
1027 |
st.markdown(
|
1028 |
"""<hr class="spends-child-seperator">""",
|
1029 |
unsafe_allow_html=True,
|
|
|
1033 |
ef1 = (_scenario.actual_total_spends/_scenario.actual_total_sales)
|
1034 |
ef2 = (_scenario.modified_total_spends/_scenario.modified_total_sales)
|
1035 |
with _columns[0]:
|
1036 |
+
st.markdown("""<h4>Cost Per Prospect</h4>""",unsafe_allow_html=True)
|
1037 |
+
# st.header("Cost Per Prospect")
|
1038 |
with _columns[1]:
|
1039 |
+
st.markdown(f"""<h4>{'$ '+numerize(ef1,0)}</h4>""",unsafe_allow_html=True)
|
1040 |
+
# st.metric(label="", value='$ '+numerize(ef1,0))
|
1041 |
with _columns[2]:
|
1042 |
+
st.markdown(f"""<h4>{'$ '+numerize(ef2,0)}</h4>""",unsafe_allow_html=True)
|
1043 |
+
# st.metric(label="", value='$ '+numerize(ef2,0))
|
1044 |
+
|
1045 |
+
if ef2 <= ef1:
|
1046 |
st.markdown(
|
1047 |
"""
|
1048 |
<style>
|
1049 |
.custom-text1 {
|
1050 |
+
font-size: 24px; /* Adjust font size */
|
1051 |
color:#6bbf6b ; /* Adjust text color */
|
1052 |
}
|
1053 |
</style>
|
1054 |
""",
|
1055 |
unsafe_allow_html=True
|
1056 |
)
|
1057 |
+
else:
|
1058 |
st.markdown(
|
1059 |
"""
|
1060 |
<style>
|
1061 |
.custom-text1 {
|
1062 |
+
font-size: 24px; /* Adjust font size */
|
1063 |
color: #ff6868; /* Adjust text color */
|
1064 |
}
|
1065 |
</style>
|
|
|
1067 |
unsafe_allow_html=True
|
1068 |
)
|
1069 |
|
1070 |
+
with _columns[3]:
|
1071 |
+
|
1072 |
+
|
1073 |
# Apply custom styles to text
|
1074 |
+
st.markdown(f'<h4 class="custom-text1">{"$ "+numerize(ef2-ef1,0)}</h4>', unsafe_allow_html=True)
|
1075 |
# st.markdown(f'<p style="color: red;">{st.metric(label="", value=header_df["Prospects"]["Change"])}</p>', unsafe_allow_html=True)
|
1076 |
# st.markdown(f'<p style="color: red;">{header_df["Prospects"]["Change"]}</p>', unsafe_allow_html=True)
|
1077 |
|
1078 |
with _columns[4]:
|
1079 |
+
# st.markdown(f'<p></hr></p>', unsafe_allow_html=True)
|
1080 |
# Apply custom styles to text
|
1081 |
+
st.markdown(f'<h4 class="custom-text1">{round((ef2-ef1)/ef1*100,2)}%</h4>', unsafe_allow_html=True)
|
1082 |
+
st.markdown("""<hr class="spends-child-seperator">""",unsafe_allow_html=True)
|
|
|
|
|
|
|
1083 |
|
1084 |
# st.markdown("""<hr class="spends-heading-seperator">""", unsafe_allow_html=True)
|
1085 |
|
|
|
1259 |
# on_change=partial(update_data_bound_max_overall)
|
1260 |
)
|
1261 |
|
1262 |
+
min_value = round(_scenario.actual_total_spends * (1-overall_lower_bound/100))
|
1263 |
+
max_value = round(_scenario.actual_total_spends * (1-overall_upper_bound/100))
|
|
|
|
|
|
|
1264 |
st.session_state["total_spends_change_abs_slider_options"] = [
|
1265 |
numerize(value, 1)
|
1266 |
for value in range(min_value, max_value + 1, int(1e4))
|
|
|
1311 |
# st.write(max_value)
|
1312 |
# for value in range(min_value, max_value + 1, int(100)):
|
1313 |
# st.write(numerize(value, 1))
|
1314 |
+
# st.session_state["total_sales_change_abs_slider_options"] = [
|
1315 |
+
# numerize(value, 1)
|
1316 |
+
# for value in range(min_value, max_value + 1, int(100))
|
1317 |
+
# ]
|
1318 |
|
1319 |
# st.select_slider(
|
1320 |
# "Absolute Slider",
|
|
|
1467 |
st.session_state["acutual_predicted"]["Delta"].append(spends_delta)
|
1468 |
_spend_cols = st.columns(2)
|
1469 |
with _spend_cols[0]:
|
1470 |
+
# st.write("Actual")
|
1471 |
+
st.markdown(f'<p> Actual <h5>{format_numbers(actual_channel_spends)}</h5> </p>', unsafe_allow_html=True)
|
1472 |
+
# st.metric(
|
1473 |
+
# label="Actual Spends",
|
1474 |
+
# value=format_numbers(actual_channel_spends),
|
1475 |
+
# # delta=numerize(spends_delta, 1),
|
1476 |
+
# # label_visibility="collapsed",
|
1477 |
+
# )
|
1478 |
+
|
1479 |
+
# st.write("Actual")
|
1480 |
+
st.markdown(f'<p> Change <h5>{format_numbers(spends_delta)}</h5> </p>', unsafe_allow_html=True)
|
1481 |
+
# st.markdown(f'<h4 class="custom-text1">{format_numbers(spends_delta)}%</h4>', unsafe_allow_html=True)
|
1482 |
+
|
1483 |
+
# st.metric(
|
1484 |
+
# label="Change",
|
1485 |
+
# value= format_numbers_f(spends_delta),
|
1486 |
+
# delta=numerize(spends_delta, 1),
|
1487 |
+
# # label_visibility="collapsed",
|
1488 |
+
# )
|
1489 |
with _spend_cols[1]:
|
1490 |
+
st.markdown(f'<p> Simulated <h5>{format_numbers(current_channel_spends)}</h5> </p>', unsafe_allow_html=True)
|
1491 |
+
st.markdown(f'<p>Percent<h5>{numerize(( spends_delta/actual_channel_spends)*100,0) +"%"}</h5> </p>', unsafe_allow_html=True)
|
1492 |
+
# st.metric(
|
1493 |
+
# label="Simulated Spends",
|
1494 |
+
# value=format_numbers(current_channel_spends),
|
1495 |
+
# # delta=numerize(spends_delta, 1),
|
1496 |
+
# # label_visibility="collapsed",
|
1497 |
+
# )
|
1498 |
+
|
1499 |
+
# st.metric(
|
1500 |
+
# label="Percent Change",
|
1501 |
+
# value= numerize(( spends_delta/actual_channel_spends)*100,0) +"%",
|
1502 |
+
# delta=numerize(spends_delta, 1),
|
1503 |
+
# # label_visibility="collapsed",
|
1504 |
+
# )
|
1505 |
|
1506 |
|
1507 |
with _columns[3]:
|
|
|
1515 |
|
1516 |
_prospect_cols = st.columns(2)
|
1517 |
with _prospect_cols[0]:
|
1518 |
+
# st.write("Actual")
|
1519 |
+
st.markdown(f'<p> Actual <h5>{format_numbers(actual_channel_sales)}</h5> </p>', unsafe_allow_html=True)
|
1520 |
+
st.markdown(f'<p> Change <h5>{format_numbers(sales_delta)}</h5> </p>', unsafe_allow_html=True)
|
1521 |
+
|
1522 |
+
# st.metric(
|
1523 |
+
# # target,
|
1524 |
+
# label="Actual Prospects",
|
1525 |
+
# value= format_numbers_f(actual_channel_sales),
|
1526 |
+
# # delta=numerize(sales_delta, 1),
|
1527 |
+
# # label_visibility="collapsed",
|
1528 |
+
# )
|
1529 |
+
# st.metric(
|
1530 |
+
# label="Change",
|
1531 |
+
# value= format_numbers_f(_channel_class.delta_sales),
|
1532 |
+
# delta=numerize(sales_delta, 1),
|
1533 |
+
# # label_visibility="collapsed",
|
1534 |
+
# )
|
1535 |
with _prospect_cols[1]:
|
1536 |
+
st.markdown(f'<p> Simulated <h5>{format_numbers(current_channel_sales)}</h5> </p>', unsafe_allow_html=True)
|
1537 |
+
st.markdown(f'<p>Percent<h5>{numerize(( _channel_class.delta_sales/actual_channel_sales)*100,0) +"%"}</h5> </p>', unsafe_allow_html=True)
|
1538 |
+
|
1539 |
+
# st.metric(
|
1540 |
+
# label="Simulated Prospects",
|
1541 |
+
# value= format_numbers_f(current_channel_sales),
|
1542 |
+
# # delta=numerize(sales_delta, 1),
|
1543 |
+
# # label_visibility="collapsed",
|
1544 |
+
# )
|
1545 |
+
|
1546 |
+
# st.metric(
|
1547 |
+
# label="Percent Change",
|
1548 |
+
# value= numerize((_channel_class.delta_sales/actual_channel_sales)*100,0) +"%",
|
1549 |
+
# delta=numerize(sales_delta, 1),
|
1550 |
+
# # label_visibility="collapsed",
|
1551 |
+
# )
|
1552 |
|
1553 |
|
1554 |
|
|
|
1592 |
|
1593 |
updated_rcs_key = f"{metrics_selected}#@{panel_selected}#@{channel_name}"
|
1594 |
|
1595 |
+
# if updated_rcs and updated_rcs_key in list(updated_rcs.keys()):
|
1596 |
+
# K = updated_rcs[updated_rcs_key]["K"]
|
1597 |
+
# b = updated_rcs[updated_rcs_key]["b"]
|
1598 |
+
# a = updated_rcs[updated_rcs_key]["a"]
|
1599 |
+
# x0 = updated_rcs[updated_rcs_key]["x0"]
|
1600 |
+
# else:
|
1601 |
+
# K = st.session_state["rcs"][col]["K"]
|
1602 |
+
# b = st.session_state["rcs"][col]["b"]
|
1603 |
+
# a = st.session_state["rcs"][col]["a"]
|
1604 |
+
# x0 = st.session_state["rcs"][col]["x0"]
|
1605 |
+
|
1606 |
+
# x_plot = np.linspace(0, 5 * x_actual.sum(), 200)
|
1607 |
+
|
1608 |
+
# # Append current_channel_spends to the end of x_plot
|
1609 |
+
# x_plot = np.append(x_plot, current_channel_spends)
|
1610 |
+
|
1611 |
+
# x, y, marginal_roi = [], [], []
|
1612 |
+
# for x_p in x_plot:
|
1613 |
+
# x.append(x_p * x_actual / x_actual.sum())
|
1614 |
+
|
1615 |
+
# for index in range(len(x_plot)):
|
1616 |
+
# y.append(s_curve(x[index] / 10**power, K, b, a, x0))
|
1617 |
+
|
1618 |
+
# for index in range(len(x_plot)):
|
1619 |
+
# marginal_roi.append(
|
1620 |
+
# a * y[index] * (1 - y[index] / np.maximum(K, np.finfo(float).eps))
|
1621 |
+
# )
|
1622 |
+
|
1623 |
+
# x = (
|
1624 |
+
# np.sum(x, axis=1)
|
1625 |
+
# * st.session_state["scenario"].channels[col].conversion_rate
|
1626 |
+
# )
|
1627 |
+
# y = np.sum(y, axis=1)
|
1628 |
+
# marginal_roi = (
|
1629 |
+
# np.average(marginal_roi, axis=1)
|
1630 |
+
# / st.session_state["scenario"].channels[col].conversion_rate
|
1631 |
+
# )
|
1632 |
|
1633 |
+
# roi = y / np.maximum(x, np.finfo(float).eps)
|
1634 |
+
# # roi = (y/np.sum(y))/(x/np.sum(x))
|
1635 |
+
# # st.write(x)
|
1636 |
+
# # st.write(y)
|
1637 |
+
# # st.write(roi)
|
1638 |
|
1639 |
+
# # st.write(roi[-1])
|
1640 |
|
1641 |
+
# roi_current, marginal_roi_current = roi[-1], marginal_roi[-1]
|
1642 |
+
# x, y, roi, marginal_roi = (
|
1643 |
+
# x[:-1],
|
1644 |
+
# y[:-1],
|
1645 |
+
# roi[:-1],
|
1646 |
+
# marginal_roi[:-1],
|
1647 |
+
# ) # Drop data for current spends
|
1648 |
+
|
1649 |
+
# # roi_current =
|
1650 |
+
|
1651 |
+
# start_value, end_value, left_value, right_value = find_segment_value(
|
1652 |
+
# x,
|
1653 |
+
# roi,
|
1654 |
+
# marginal_roi,
|
1655 |
+
# )
|
1656 |
|
1657 |
#st.write(roi_current)
|
1658 |
|
1659 |
+
# rgba = calculate_rgba(
|
1660 |
+
# start_value,
|
1661 |
+
# end_value,
|
1662 |
+
# left_value,
|
1663 |
+
# right_value,
|
1664 |
+
# current_channel_spends,
|
1665 |
+
# )
|
1666 |
|
1667 |
summary_df = pd.DataFrame(st.session_state["acutual_predicted"])
|
1668 |
# st.dataframe(summary_df)
|
|
|
1700 |
text-align: center;
|
1701 |
color: {'black'};
|
1702 |
">
|
1703 |
+
<p style="margin: 0; font-size: 16px;">Simulated Efficiency: {round(a,2)} </br> Actual Efficiency: {round(b,2)} </p>
|
1704 |
+
<!--<p style="margin: 0; font-size: 16px;">Marginal ROI: {round(b,1)}</p>-->
|
1705 |
</div>
|
1706 |
""",
|
1707 |
unsafe_allow_html=True,
|
1708 |
)
|
1709 |
+
# <p style="margin: 0; font-size: 16px;">Simulated Efficiency: {round(a,2)} </br> Actual Efficiency: {round(b,2)} </p>
|
1710 |
+
# <!--<p style="margin: 0; font-size: 16px;">Marginal ROI: {round(b,1)}</p>-->
|
1711 |
|
1712 |
with st.expander("See Response Curves", expanded=True):
|
1713 |
fig = plot_response_curves(summary_df_sorted)
|
pages/3_Saved_Scenarios.py
CHANGED
@@ -405,6 +405,7 @@ if auth_status == True:
|
|
405 |
# 'Pick a scenario to view details',
|
406 |
# list(saved_scenarios.keys())
|
407 |
# )
|
|
|
408 |
with st.expander('Download Scenario'):
|
409 |
st.markdown("""<hr>""", unsafe_allow_html=True)
|
410 |
scenarios_to_download = st.multiselect('Select scenarios to download',
|
@@ -429,8 +430,9 @@ if auth_status == True:
|
|
429 |
column_1, column_2,column_3 = st.columns((6,1,1))
|
430 |
with column_1:
|
431 |
st.header(selected_scenario)
|
432 |
-
with column_3:
|
433 |
-
|
|
|
434 |
# with column_3:
|
435 |
# st.button('Load Scenario', on_click=load_scenario)
|
436 |
|
|
|
405 |
# 'Pick a scenario to view details',
|
406 |
# list(saved_scenarios.keys())
|
407 |
# )
|
408 |
+
st.button('Delete scenario', on_click=delete_scenario)
|
409 |
with st.expander('Download Scenario'):
|
410 |
st.markdown("""<hr>""", unsafe_allow_html=True)
|
411 |
scenarios_to_download = st.multiselect('Select scenarios to download',
|
|
|
430 |
column_1, column_2,column_3 = st.columns((6,1,1))
|
431 |
with column_1:
|
432 |
st.header(selected_scenario)
|
433 |
+
# with column_3:
|
434 |
+
# st.write("")
|
435 |
+
# st.button('Delete scenario', on_click=delete_scenario)
|
436 |
# with column_3:
|
437 |
# st.button('Load Scenario', on_click=load_scenario)
|
438 |
|
response_curves_model_quality.py
CHANGED
@@ -125,7 +125,7 @@ def data_output(channel,X,y,y_fit_inv,x_ext_data,y_fit_inv_ext):
|
|
125 |
|
126 |
ext_df['MAT'] = ["ext","ext","ext"]
|
127 |
|
128 |
-
print(ext_df)
|
129 |
plot_df= plot_df.append(ext_df)
|
130 |
return plot_df
|
131 |
|
@@ -148,7 +148,7 @@ def input_data(df,spend_col,prospect_col):
|
|
148 |
return X,y,x_data,y_data,x_minmax,y_minmax
|
149 |
|
150 |
def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
151 |
-
print(x_max)
|
152 |
x_ext_data = [x_max*1.2,x_max*1.3,x_max*1.5]
|
153 |
# x_ext_data = [1500000,2000000,2500000]
|
154 |
# x_ext_data = [x_max+100,x_max+200,x_max+5000]
|
@@ -157,7 +157,7 @@ def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
|
157 |
for i in range(len(x_scaled)):
|
158 |
x_data.append(x_scaled[i][0])
|
159 |
|
160 |
-
print(x_data)
|
161 |
y_fit = hill_equation(x_data, Kd_fit, n_fit)
|
162 |
y_fit_inv = y_minmax.inverse_transform(np.array(y_fit).reshape(-1,1))
|
163 |
|
@@ -170,8 +170,8 @@ def fit_data(spend_col,prospect_col,channel):
|
|
170 |
|
171 |
X,y,x_data,y_data,x_minmax,y_minmax = input_data(temp_df,spend_col,prospect_col)
|
172 |
y_fit, y_fit_inv, Kd_fit, n_fit = hill_func(x_data,y_data,x_minmax,y_minmax)
|
173 |
-
print('k: ',Kd_fit)
|
174 |
-
print('n: ', n_fit)
|
175 |
|
176 |
##### extend_s_curve
|
177 |
x_ext_data,y_fit_inv_ext= extend_s_curve(temp_df[spend_col].max(),x_minmax,y_minmax, Kd_fit, n_fit)
|
@@ -183,7 +183,7 @@ plotly_data = fit_data(spend_cols[0],prospect_cols[0],channel_cols[0])
|
|
183 |
plotly_data.tail()
|
184 |
|
185 |
for i in range(1,13):
|
186 |
-
print(i)
|
187 |
pdf = fit_data(spend_cols[i],prospect_cols[i],channel_cols[i])
|
188 |
plotly_data = plotly_data.merge(pdf,on = ["Date","MAT"],how = "left")
|
189 |
|
@@ -223,8 +223,8 @@ def response_curves(channel,x_modified,y_modified):
|
|
223 |
))
|
224 |
|
225 |
fig.add_trace(go.Scatter(
|
226 |
-
x=[x_modified],
|
227 |
-
y=[y_modified],
|
228 |
mode='markers',
|
229 |
marker=dict(
|
230 |
size=13 # Adjust the size value to make the markers larger or smaller
|
@@ -369,7 +369,7 @@ def data_output(channel,X,y,y_fit_inv,x_ext_data,y_fit_inv_ext):
|
|
369 |
|
370 |
ext_df['MAT'] = ["ext","ext","ext"]
|
371 |
|
372 |
-
print(ext_df)
|
373 |
plot_df= plot_df.append(ext_df)
|
374 |
return plot_df
|
375 |
|
@@ -392,7 +392,7 @@ def input_data(df,spend_col,prospect_col):
|
|
392 |
return X,y,x_data,y_data,x_minmax,y_minmax
|
393 |
|
394 |
def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
395 |
-
print(x_max)
|
396 |
x_ext_data = [x_max*1.2,x_max*1.3,x_max*1.5]
|
397 |
# x_ext_data = [1500000,2000000,2500000]
|
398 |
# x_ext_data = [x_max+100,x_max+200,x_max+5000]
|
@@ -401,7 +401,7 @@ def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
|
401 |
for i in range(len(x_scaled)):
|
402 |
x_data.append(x_scaled[i][0])
|
403 |
|
404 |
-
print(x_data)
|
405 |
y_fit = hill_equation(x_data, Kd_fit, n_fit)
|
406 |
y_fit_inv = y_minmax.inverse_transform(np.array(y_fit).reshape(-1,1))
|
407 |
|
@@ -414,8 +414,8 @@ def fit_data(spend_col,prospect_col,channel):
|
|
414 |
|
415 |
X,y,x_data,y_data,x_minmax,y_minmax = input_data(temp_df,spend_col,prospect_col)
|
416 |
y_fit, y_fit_inv, Kd_fit, n_fit = hill_func(x_data,y_data,x_minmax,y_minmax)
|
417 |
-
print('k: ',Kd_fit)
|
418 |
-
print('n: ', n_fit)
|
419 |
|
420 |
##### extend_s_curve
|
421 |
x_ext_data,y_fit_inv_ext= extend_s_curve(temp_df[spend_col].max(),x_minmax,y_minmax, Kd_fit, n_fit)
|
@@ -427,7 +427,7 @@ plotly_data = fit_data(spend_cols[0],prospect_cols[0],channel_cols[0])
|
|
427 |
plotly_data.tail()
|
428 |
|
429 |
for i in range(1,13):
|
430 |
-
print(i)
|
431 |
pdf = fit_data(spend_cols[i],prospect_cols[i],channel_cols[i])
|
432 |
plotly_data = plotly_data.merge(pdf,on = ["Date","MAT"],how = "left")
|
433 |
|
|
|
125 |
|
126 |
ext_df['MAT'] = ["ext","ext","ext"]
|
127 |
|
128 |
+
# print(ext_df)
|
129 |
plot_df= plot_df.append(ext_df)
|
130 |
return plot_df
|
131 |
|
|
|
148 |
return X,y,x_data,y_data,x_minmax,y_minmax
|
149 |
|
150 |
def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
151 |
+
# print(x_max)
|
152 |
x_ext_data = [x_max*1.2,x_max*1.3,x_max*1.5]
|
153 |
# x_ext_data = [1500000,2000000,2500000]
|
154 |
# x_ext_data = [x_max+100,x_max+200,x_max+5000]
|
|
|
157 |
for i in range(len(x_scaled)):
|
158 |
x_data.append(x_scaled[i][0])
|
159 |
|
160 |
+
# print(x_data)
|
161 |
y_fit = hill_equation(x_data, Kd_fit, n_fit)
|
162 |
y_fit_inv = y_minmax.inverse_transform(np.array(y_fit).reshape(-1,1))
|
163 |
|
|
|
170 |
|
171 |
X,y,x_data,y_data,x_minmax,y_minmax = input_data(temp_df,spend_col,prospect_col)
|
172 |
y_fit, y_fit_inv, Kd_fit, n_fit = hill_func(x_data,y_data,x_minmax,y_minmax)
|
173 |
+
# print('k: ',Kd_fit)
|
174 |
+
# print('n: ', n_fit)
|
175 |
|
176 |
##### extend_s_curve
|
177 |
x_ext_data,y_fit_inv_ext= extend_s_curve(temp_df[spend_col].max(),x_minmax,y_minmax, Kd_fit, n_fit)
|
|
|
183 |
plotly_data.tail()
|
184 |
|
185 |
for i in range(1,13):
|
186 |
+
# print(i)
|
187 |
pdf = fit_data(spend_cols[i],prospect_cols[i],channel_cols[i])
|
188 |
plotly_data = plotly_data.merge(pdf,on = ["Date","MAT"],how = "left")
|
189 |
|
|
|
223 |
))
|
224 |
|
225 |
fig.add_trace(go.Scatter(
|
226 |
+
x=[x_modified/104],
|
227 |
+
y=[y_modified/104],
|
228 |
mode='markers',
|
229 |
marker=dict(
|
230 |
size=13 # Adjust the size value to make the markers larger or smaller
|
|
|
369 |
|
370 |
ext_df['MAT'] = ["ext","ext","ext"]
|
371 |
|
372 |
+
# print(ext_df)
|
373 |
plot_df= plot_df.append(ext_df)
|
374 |
return plot_df
|
375 |
|
|
|
392 |
return X,y,x_data,y_data,x_minmax,y_minmax
|
393 |
|
394 |
def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
395 |
+
# print(x_max)
|
396 |
x_ext_data = [x_max*1.2,x_max*1.3,x_max*1.5]
|
397 |
# x_ext_data = [1500000,2000000,2500000]
|
398 |
# x_ext_data = [x_max+100,x_max+200,x_max+5000]
|
|
|
401 |
for i in range(len(x_scaled)):
|
402 |
x_data.append(x_scaled[i][0])
|
403 |
|
404 |
+
# print(x_data)
|
405 |
y_fit = hill_equation(x_data, Kd_fit, n_fit)
|
406 |
y_fit_inv = y_minmax.inverse_transform(np.array(y_fit).reshape(-1,1))
|
407 |
|
|
|
414 |
|
415 |
X,y,x_data,y_data,x_minmax,y_minmax = input_data(temp_df,spend_col,prospect_col)
|
416 |
y_fit, y_fit_inv, Kd_fit, n_fit = hill_func(x_data,y_data,x_minmax,y_minmax)
|
417 |
+
# print('k: ',Kd_fit)
|
418 |
+
# print('n: ', n_fit)
|
419 |
|
420 |
##### extend_s_curve
|
421 |
x_ext_data,y_fit_inv_ext= extend_s_curve(temp_df[spend_col].max(),x_minmax,y_minmax, Kd_fit, n_fit)
|
|
|
427 |
plotly_data.tail()
|
428 |
|
429 |
for i in range(1,13):
|
430 |
+
# print(i)
|
431 |
pdf = fit_data(spend_cols[i],prospect_cols[i],channel_cols[i])
|
432 |
plotly_data = plotly_data.merge(pdf,on = ["Date","MAT"],how = "left")
|
433 |
|
response_curves_model_quality_base.py
CHANGED
@@ -125,7 +125,7 @@ def data_output(channel,X,y,y_fit_inv,x_ext_data,y_fit_inv_ext):
|
|
125 |
|
126 |
ext_df['MAT'] = ["ext","ext","ext"]
|
127 |
|
128 |
-
print(ext_df.columns)
|
129 |
plot_df= plot_df.append(ext_df)
|
130 |
return plot_df
|
131 |
|
@@ -148,7 +148,7 @@ def input_data(df,spend_col,prospect_col):
|
|
148 |
return X,y,x_data,y_data,x_minmax,y_minmax
|
149 |
|
150 |
def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
151 |
-
print(x_max)
|
152 |
x_ext_data = [x_max*1.2,x_max*1.3,x_max*1.5]
|
153 |
# x_ext_data = [1500000,2000000,2500000]
|
154 |
# x_ext_data = [x_max+100,x_max+200,x_max+5000]
|
@@ -157,7 +157,7 @@ def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
|
157 |
for i in range(len(x_scaled)):
|
158 |
x_data.append(x_scaled[i][0])
|
159 |
|
160 |
-
print(x_data)
|
161 |
y_fit = hill_equation(x_data, Kd_fit, n_fit)
|
162 |
y_fit_inv = y_minmax.inverse_transform(np.array(y_fit).reshape(-1,1))
|
163 |
|
@@ -170,8 +170,8 @@ def fit_data(spend_col,prospect_col,channel):
|
|
170 |
|
171 |
X,y,x_data,y_data,x_minmax,y_minmax = input_data(temp_df,spend_col,prospect_col)
|
172 |
y_fit, y_fit_inv, Kd_fit, n_fit = hill_func(x_data,y_data,x_minmax,y_minmax)
|
173 |
-
print('k: ',Kd_fit)
|
174 |
-
print('n: ', n_fit)
|
175 |
|
176 |
##### extend_s_curve
|
177 |
x_ext_data,y_fit_inv_ext= extend_s_curve(temp_df[spend_col].max(),x_minmax,y_minmax, Kd_fit, n_fit)
|
@@ -190,23 +190,59 @@ for i in range(1,13):
|
|
190 |
def response_curves(channel,chart_typ):
|
191 |
if chart_typ == 'View Scattered Plot':
|
192 |
mode_f1 = "markers"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
elif chart_typ == 'View Line Plot':
|
194 |
mode_f1 = "lines"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
else:
|
196 |
-
mode_f1 = "
|
197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
-
|
200 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
|
202 |
-
|
203 |
-
y_col = "Fit_Data_"+channel
|
204 |
-
fig.add_trace(go.Scatter(
|
205 |
-
x=plotly_data.sort_values(by=x_col, ascending=True)[x_col],
|
206 |
-
y=plotly_data.sort_values(by=x_col, ascending=True)[y_col],
|
207 |
-
mode=mode_f1,
|
208 |
-
name=x_col.replace('_Spends', '')
|
209 |
-
))
|
210 |
plotly_data2 = plotly_data[plotly_data[x_col].isnull()==False]
|
211 |
# import steamlit as st
|
212 |
# st.dataframe()
|
|
|
125 |
|
126 |
ext_df['MAT'] = ["ext","ext","ext"]
|
127 |
|
128 |
+
# print(ext_df.columns)
|
129 |
plot_df= plot_df.append(ext_df)
|
130 |
return plot_df
|
131 |
|
|
|
148 |
return X,y,x_data,y_data,x_minmax,y_minmax
|
149 |
|
150 |
def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
151 |
+
# print(x_max)
|
152 |
x_ext_data = [x_max*1.2,x_max*1.3,x_max*1.5]
|
153 |
# x_ext_data = [1500000,2000000,2500000]
|
154 |
# x_ext_data = [x_max+100,x_max+200,x_max+5000]
|
|
|
157 |
for i in range(len(x_scaled)):
|
158 |
x_data.append(x_scaled[i][0])
|
159 |
|
160 |
+
# print(x_data)
|
161 |
y_fit = hill_equation(x_data, Kd_fit, n_fit)
|
162 |
y_fit_inv = y_minmax.inverse_transform(np.array(y_fit).reshape(-1,1))
|
163 |
|
|
|
170 |
|
171 |
X,y,x_data,y_data,x_minmax,y_minmax = input_data(temp_df,spend_col,prospect_col)
|
172 |
y_fit, y_fit_inv, Kd_fit, n_fit = hill_func(x_data,y_data,x_minmax,y_minmax)
|
173 |
+
# print('k: ',Kd_fit)
|
174 |
+
# print('n: ', n_fit)
|
175 |
|
176 |
##### extend_s_curve
|
177 |
x_ext_data,y_fit_inv_ext= extend_s_curve(temp_df[spend_col].max(),x_minmax,y_minmax, Kd_fit, n_fit)
|
|
|
190 |
def response_curves(channel,chart_typ):
|
191 |
if chart_typ == 'View Scattered Plot':
|
192 |
mode_f1 = "markers"
|
193 |
+
# Initialize the Plotly figure
|
194 |
+
fig = go.Figure()
|
195 |
+
|
196 |
+
x_col = channel+"_Spends"
|
197 |
+
y_col = channel+"_Prospects"
|
198 |
+
fig.add_trace(go.Scatter(
|
199 |
+
x=plotly_data.sort_values(by=x_col, ascending=True)[x_col],
|
200 |
+
y=plotly_data.sort_values(by=x_col, ascending=True)[y_col],
|
201 |
+
mode=mode_f1,
|
202 |
+
name=x_col.replace('_Spends', '')
|
203 |
+
))
|
204 |
elif chart_typ == 'View Line Plot':
|
205 |
mode_f1 = "lines"
|
206 |
+
# Initialize the Plotly figure
|
207 |
+
fig = go.Figure()
|
208 |
+
|
209 |
+
x_col = channel+"_Spends"
|
210 |
+
y_col = 'Fit_Data_'+channel
|
211 |
+
fig.add_trace(go.Scatter(
|
212 |
+
x=plotly_data.sort_values(by=x_col, ascending=True)[x_col],
|
213 |
+
y=plotly_data.sort_values(by=x_col, ascending=True)[y_col],
|
214 |
+
mode=mode_f1,
|
215 |
+
name=x_col.replace('_Spends', '')
|
216 |
+
))
|
217 |
else:
|
218 |
+
mode_f1 = "markers"
|
219 |
+
# Initialize the Plotly figure
|
220 |
+
fig = go.Figure()
|
221 |
+
|
222 |
+
x_col = channel+"_Spends"
|
223 |
+
y_col = channel+"_Prospects"
|
224 |
+
fig.add_trace(go.Scatter(
|
225 |
+
x=plotly_data.sort_values(by=x_col, ascending=True)[x_col],
|
226 |
+
y=plotly_data.sort_values(by=x_col, ascending=True)[y_col],
|
227 |
+
mode=mode_f1,
|
228 |
+
name=x_col.replace('_Spends', '')
|
229 |
+
))
|
230 |
|
231 |
+
# mode_f1 = "lines+markers"
|
232 |
+
mode_f1 = "lines"
|
233 |
+
# Initialize the Plotly figure
|
234 |
+
# fig = go.Figure()
|
235 |
+
|
236 |
+
x_col = channel+"_Spends"
|
237 |
+
y_col = 'Fit_Data_'+channel
|
238 |
+
fig.add_trace(go.Scatter(
|
239 |
+
x=plotly_data.sort_values(by=x_col, ascending=True)[x_col],
|
240 |
+
y=plotly_data.sort_values(by=x_col, ascending=True)[y_col],
|
241 |
+
mode=mode_f1,
|
242 |
+
name=x_col.replace('_Spends', '')
|
243 |
+
))
|
244 |
|
245 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
plotly_data2 = plotly_data[plotly_data[x_col].isnull()==False]
|
247 |
# import steamlit as st
|
248 |
# st.dataframe()
|
summary_df.pkl
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
size 1822
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:bbfe530ac30a045842611782bde814043862ff721a910f19cfbb8525f1dfb82a
|
3 |
size 1822
|
utilities.py
CHANGED
@@ -221,14 +221,10 @@ def initialize_data(
|
|
221 |
contri_df = excel["CONTRIBUTION MMM"]
|
222 |
|
223 |
# Check if the panel is not None
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
elif panel == "Total Market":
|
229 |
-
raw_df = panel_level(raw_df, date_column="Date")
|
230 |
-
spend_df = panel_level(spend_df, date_column="Week")
|
231 |
-
contri_df = panel_level(contri_df, date_column="Date")
|
232 |
|
233 |
# Revenue_df = excel['Revenue']
|
234 |
|
@@ -294,48 +290,21 @@ def initialize_data(
|
|
294 |
##output cols aggregation
|
295 |
output_cols.append(out_col)
|
296 |
|
297 |
-
|
298 |
-
|
299 |
-
if power >= 0:
|
300 |
-
x = x / 10**power
|
301 |
-
|
302 |
-
x = x.astype("float64")
|
303 |
-
y = y.astype("float64")
|
304 |
-
# print('#printing yyyyyyyyy')
|
305 |
-
# print(inp_col)
|
306 |
-
# print(x.max())
|
307 |
-
# print(y.max())
|
308 |
-
bounds = ((0, 0, 0, 0), (3 * y.max(), 1000, 1, x.max()))
|
309 |
-
|
310 |
-
# bounds = ((y.max(), 3*y.max()),(0,1000),(0,1),(0,x.max()))
|
311 |
-
params, _ = curve_fit(
|
312 |
-
s_curve,
|
313 |
-
x,
|
314 |
-
y,
|
315 |
-
p0=(2 * y.max(), 0.01, 1e-5, x.max()),
|
316 |
-
bounds=bounds,
|
317 |
-
maxfev=int(1e5),
|
318 |
-
)
|
319 |
-
mape = (100 * abs(1 - s_curve(x, *params) / y.clip(min=1))).mean()
|
320 |
-
rmse = np.sqrt(((y - s_curve(x, *params)) ** 2).mean())
|
321 |
-
r2_ = r2_score(y, s_curve(x, *params))
|
322 |
-
|
323 |
response_curves[inp_col] = {
|
324 |
-
"
|
325 |
-
"
|
326 |
-
"
|
327 |
-
"
|
|
|
|
|
328 |
}
|
329 |
|
330 |
updated_rcs_key = f"{metrics}#@{panel}#@{inp_col}"
|
331 |
if updated_rcs is not None and updated_rcs_key in list(updated_rcs.keys()):
|
332 |
response_curves[inp_col] = updated_rcs[updated_rcs_key]
|
333 |
|
334 |
-
mapes[inp_col] = mape
|
335 |
-
rmses[inp_col] = rmse
|
336 |
-
r2[inp_col] = r2_
|
337 |
-
powers[inp_col] = power
|
338 |
-
|
339 |
## conversion rates
|
340 |
spend_col = [
|
341 |
_col
|
@@ -362,14 +331,17 @@ def initialize_data(
|
|
362 |
name=inp_col,
|
363 |
dates=dates,
|
364 |
spends=spends,
|
|
|
365 |
# conversion_rate = np.mean(list(conv_rates[inp_col].values())),
|
366 |
conversion_rate=conv_rates[inp_col],
|
367 |
-
response_curve_type="
|
368 |
response_curve_params={
|
369 |
-
"
|
370 |
-
"
|
371 |
-
"
|
372 |
-
"
|
|
|
|
|
373 |
},
|
374 |
bounds=np.array([-10, 10]),
|
375 |
channel_bounds_min = 10,
|
@@ -430,94 +402,6 @@ def initialize_data(
|
|
430 |
st.session_state["disable_download_button"] = True
|
431 |
|
432 |
|
433 |
-
# def initialize_data():
|
434 |
-
# # fetch data from excel
|
435 |
-
# output = pd.read_excel('data.xlsx',sheet_name=None)
|
436 |
-
# raw_df = output['RAW DATA MMM']
|
437 |
-
# contribution_df = output['CONTRIBUTION MMM']
|
438 |
-
# Revenue_df = output['Revenue']
|
439 |
-
|
440 |
-
# ## channels to be shows
|
441 |
-
# channel_list = []
|
442 |
-
# for col in raw_df.columns:
|
443 |
-
# if 'click' in col.lower() or 'spend' in col.lower() or 'imp' in col.lower():
|
444 |
-
# ##print(col)
|
445 |
-
# channel_list.append(col)
|
446 |
-
# else:
|
447 |
-
# pass
|
448 |
-
|
449 |
-
# ## NOTE : Considered only Desktop spends for all calculations
|
450 |
-
# acutal_df = raw_df[raw_df.Region == 'Desktop'].copy()
|
451 |
-
# ## NOTE : Considered one year of data
|
452 |
-
# acutal_df = acutal_df[acutal_df.Date>'2020-12-31']
|
453 |
-
# actual_df = acutal_df.drop('Region',axis=1).sort_values(by='Date')[[*channel_list,'Date']]
|
454 |
-
|
455 |
-
# ##load response curves
|
456 |
-
# with open('./grammarly_response_curves.json','r') as f:
|
457 |
-
# response_curves = json.load(f)
|
458 |
-
|
459 |
-
# ## create channel dict for scenario creation
|
460 |
-
# dates = actual_df.Date.values
|
461 |
-
# channels = {}
|
462 |
-
# rcs = {}
|
463 |
-
# constant = 0.
|
464 |
-
# for i,info_dict in enumerate(response_curves):
|
465 |
-
# name = info_dict.get('name')
|
466 |
-
# response_curve_type = info_dict.get('response_curve')
|
467 |
-
# response_curve_params = info_dict.get('params')
|
468 |
-
# rcs[name] = response_curve_params
|
469 |
-
# if name != 'constant':
|
470 |
-
# spends = actual_df[name].values
|
471 |
-
# channel = Channel(name=name,dates=dates,
|
472 |
-
# spends=spends,
|
473 |
-
# response_curve_type=response_curve_type,
|
474 |
-
# response_curve_params=response_curve_params,
|
475 |
-
# bounds=np.array([-30,30]))
|
476 |
-
|
477 |
-
# channels[name] = channel
|
478 |
-
# else:
|
479 |
-
# constant = info_dict.get('value',0.) * len(dates)
|
480 |
-
|
481 |
-
# ## create scenario
|
482 |
-
# scenario = Scenario(name='default', channels=channels, constant=constant)
|
483 |
-
# default_scenario_dict = class_to_dict(scenario)
|
484 |
-
|
485 |
-
|
486 |
-
# ## setting session variables
|
487 |
-
# st.session_state['initialized'] = True
|
488 |
-
# st.session_state['actual_df'] = actual_df
|
489 |
-
# st.session_state['raw_df'] = raw_df
|
490 |
-
# st.session_state['default_scenario_dict'] = default_scenario_dict
|
491 |
-
# st.session_state['scenario'] = scenario
|
492 |
-
# st.session_state['channels_list'] = channel_list
|
493 |
-
# st.session_state['optimization_channels'] = {channel_name : False for channel_name in channel_list}
|
494 |
-
# st.session_state['rcs'] = rcs
|
495 |
-
# for channel in channels.values():
|
496 |
-
# if channel.name not in st.session_state:
|
497 |
-
# st.session_state[channel.name] = float(channel.actual_total_spends)
|
498 |
-
|
499 |
-
# if 'xlsx_buffer' not in st.session_state:
|
500 |
-
# st.session_state['xlsx_buffer'] = io.BytesIO()
|
501 |
-
|
502 |
-
# ## for saving scenarios
|
503 |
-
# if 'saved_scenarios' not in st.session_state:
|
504 |
-
# if Path('../saved_scenarios.pkl').exists():
|
505 |
-
# with open('../saved_scenarios.pkl','rb') as f:
|
506 |
-
# st.session_state['saved_scenarios'] = pickle.load(f)
|
507 |
-
|
508 |
-
# else:
|
509 |
-
# st.session_state['saved_scenarios'] = OrderedDict()
|
510 |
-
|
511 |
-
# if 'total_spends_change' not in st.session_state:
|
512 |
-
# st.session_state['total_spends_change'] = 0
|
513 |
-
|
514 |
-
# if 'optimization_channels' not in st.session_state:
|
515 |
-
# st.session_state['optimization_channels'] = {channel_name : False for channel_name in channel_list}
|
516 |
-
|
517 |
-
# if 'disable_download_button' not in st.session_state:
|
518 |
-
# st.session_state['disable_download_button'] = True
|
519 |
-
|
520 |
-
|
521 |
def create_channel_summary(scenario):
|
522 |
|
523 |
# Provided data
|
@@ -618,90 +502,6 @@ def create_channel_summary(scenario):
|
|
618 |
return df
|
619 |
|
620 |
|
621 |
-
# @st.cache(allow_output_mutation=True)
|
622 |
-
# def create_contribution_pie(scenario):
|
623 |
-
# #c1f7dc
|
624 |
-
# colors_map = {col:color for col,color in zip(st.session_state['channels_list'],plotly.colors.n_colors(plotly.colors.hex_to_rgb('#BE6468'), plotly.colors.hex_to_rgb('#E7B8B7'),23))}
|
625 |
-
# total_contribution_fig = make_subplots(rows=1, cols=2,subplot_titles=['Spends','Revenue'],specs=[[{"type": "pie"}, {"type": "pie"}]])
|
626 |
-
# total_contribution_fig.add_trace(
|
627 |
-
# go.Pie(labels=[channel_name_formating(channel_name) for channel_name in st.session_state['channels_list']] + ['Non Media'],
|
628 |
-
# values= [round(scenario.channels[channel_name].actual_total_spends * scenario.channels[channel_name].conversion_rate,1) for channel_name in st.session_state['channels_list']] + [0],
|
629 |
-
# marker=dict(colors = [plotly.colors.label_rgb(colors_map[channel_name]) for channel_name in st.session_state['channels_list']] + ['#F0F0F0']),
|
630 |
-
# hole=0.3),
|
631 |
-
# row=1, col=1)
|
632 |
-
|
633 |
-
# total_contribution_fig.add_trace(
|
634 |
-
# go.Pie(labels=[channel_name_formating(channel_name) for channel_name in st.session_state['channels_list']] + ['Non Media'],
|
635 |
-
# values= [scenario.channels[channel_name].actual_total_sales for channel_name in st.session_state['channels_list']] + [scenario.correction.sum() + scenario.constant.sum()],
|
636 |
-
# hole=0.3),
|
637 |
-
# row=1, col=2)
|
638 |
-
|
639 |
-
# total_contribution_fig.update_traces(textposition='inside',texttemplate='%{percent:.1%}')
|
640 |
-
# total_contribution_fig.update_layout(uniformtext_minsize=12,title='Channel contribution', uniformtext_mode='hide')
|
641 |
-
# return total_contribution_fig
|
642 |
-
|
643 |
-
# @st.cache(allow_output_mutation=True)
|
644 |
-
|
645 |
-
# def create_contribuion_stacked_plot(scenario):
|
646 |
-
# weekly_contribution_fig = make_subplots(rows=1, cols=2,subplot_titles=['Spends','Revenue'],specs=[[{"type": "bar"}, {"type": "bar"}]])
|
647 |
-
# raw_df = st.session_state['raw_df']
|
648 |
-
# df = raw_df.sort_values(by='Date')
|
649 |
-
# x = df.Date
|
650 |
-
# weekly_spends_data = []
|
651 |
-
# weekly_sales_data = []
|
652 |
-
# for channel_name in st.session_state['channels_list']:
|
653 |
-
# weekly_spends_data.append((go.Bar(x=x,
|
654 |
-
# y=scenario.channels[channel_name].actual_spends * scenario.channels[channel_name].conversion_rate,
|
655 |
-
# name=channel_name_formating(channel_name),
|
656 |
-
# hovertemplate="Date:%{x}<br>Spend:%{y:$.2s}",
|
657 |
-
# legendgroup=channel_name)))
|
658 |
-
# weekly_sales_data.append((go.Bar(x=x,
|
659 |
-
# y=scenario.channels[channel_name].actual_sales,
|
660 |
-
# name=channel_name_formating(channel_name),
|
661 |
-
# hovertemplate="Date:%{x}<br>Revenue:%{y:$.2s}",
|
662 |
-
# legendgroup=channel_name, showlegend=False)))
|
663 |
-
# for _d in weekly_spends_data:
|
664 |
-
# weekly_contribution_fig.add_trace(_d, row=1, col=1)
|
665 |
-
# for _d in weekly_sales_data:
|
666 |
-
# weekly_contribution_fig.add_trace(_d, row=1, col=2)
|
667 |
-
# weekly_contribution_fig.add_trace(go.Bar(x=x,
|
668 |
-
# y=scenario.constant + scenario.correction,
|
669 |
-
# name='Non Media',
|
670 |
-
# hovertemplate="Date:%{x}<br>Revenue:%{y:$.2s}"), row=1, col=2)
|
671 |
-
# weekly_contribution_fig.update_layout(barmode='stack', title='Channel contribuion by week', xaxis_title='Date')
|
672 |
-
# weekly_contribution_fig.update_xaxes(showgrid=False)
|
673 |
-
# weekly_contribution_fig.update_yaxes(showgrid=False)
|
674 |
-
# return weekly_contribution_fig
|
675 |
-
|
676 |
-
# @st.cache(allow_output_mutation=True)
|
677 |
-
# def create_channel_spends_sales_plot(channel):
|
678 |
-
# if channel is not None:
|
679 |
-
# x = channel.dates
|
680 |
-
# _spends = channel.actual_spends * channel.conversion_rate
|
681 |
-
# _sales = channel.actual_sales
|
682 |
-
# channel_sales_spends_fig = make_subplots(specs=[[{"secondary_y": True}]])
|
683 |
-
# channel_sales_spends_fig.add_trace(go.Bar(x=x, y=_sales,marker_color='#c1f7dc',name='Revenue', hovertemplate="Date:%{x}<br>Revenue:%{y:$.2s}"), secondary_y = False)
|
684 |
-
# channel_sales_spends_fig.add_trace(go.Scatter(x=x, y=_spends,line=dict(color='#005b96'),name='Spends',hovertemplate="Date:%{x}<br>Spend:%{y:$.2s}"), secondary_y = True)
|
685 |
-
# channel_sales_spends_fig.update_layout(xaxis_title='Date',yaxis_title='Revenue',yaxis2_title='Spends ($)',title='Channel spends and Revenue week wise')
|
686 |
-
# channel_sales_spends_fig.update_xaxes(showgrid=False)
|
687 |
-
# channel_sales_spends_fig.update_yaxes(showgrid=False)
|
688 |
-
# else:
|
689 |
-
# raw_df = st.session_state['raw_df']
|
690 |
-
# df = raw_df.sort_values(by='Date')
|
691 |
-
# x = df.Date
|
692 |
-
# scenario = class_from_dict(st.session_state['default_scenario_dict'])
|
693 |
-
# _sales = scenario.constant + scenario.correction
|
694 |
-
# channel_sales_spends_fig = make_subplots(specs=[[{"secondary_y": True}]])
|
695 |
-
# channel_sales_spends_fig.add_trace(go.Bar(x=x, y=_sales,marker_color='#c1f7dc',name='Revenue', hovertemplate="Date:%{x}<br>Revenue:%{y:$.2s}"), secondary_y = False)
|
696 |
-
# # channel_sales_spends_fig.add_trace(go.Scatter(x=x, y=_spends,line=dict(color='#15C39A'),name='Spends',hovertemplate="Date:%{x}<br>Spend:%{y:$.2s}"), secondary_y = True)
|
697 |
-
# channel_sales_spends_fig.update_layout(xaxis_title='Date',yaxis_title='Revenue',yaxis2_title='Spends ($)',title='Channel spends and Revenue week wise')
|
698 |
-
# channel_sales_spends_fig.update_xaxes(showgrid=False)
|
699 |
-
# channel_sales_spends_fig.update_yaxes(showgrid=False)
|
700 |
-
# return channel_sales_spends_fig
|
701 |
-
|
702 |
-
|
703 |
-
# Define a shared color palette
|
704 |
-
|
705 |
|
706 |
def create_contribution_pie():
|
707 |
color_palette = [
|
|
|
221 |
contri_df = excel["CONTRIBUTION MMM"]
|
222 |
|
223 |
# Check if the panel is not None
|
224 |
+
|
225 |
+
raw_df = panel_level(raw_df, date_column="Date")
|
226 |
+
spend_df = panel_level(spend_df, date_column="Week")
|
227 |
+
contri_df = panel_level(contri_df, date_column="Date")
|
|
|
|
|
|
|
|
|
228 |
|
229 |
# Revenue_df = excel['Revenue']
|
230 |
|
|
|
290 |
##output cols aggregation
|
291 |
output_cols.append(out_col)
|
292 |
|
293 |
+
params = pd.read_excel(r"C:\Users\PragyaJatav\Downloads\Untitled Folder 2\simulator uploaded - Copy\Simulator-UOPX\response_curves_parameters.xlsx",index_col = "channel")
|
294 |
+
param_dicts = {col: params[col].to_dict() for col in params.columns}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
295 |
response_curves[inp_col] = {
|
296 |
+
"Kd": param_dicts["Kd"][inp_col],
|
297 |
+
"n": param_dicts["n"][inp_col],
|
298 |
+
"x_min": param_dicts["x_min"][inp_col],
|
299 |
+
"x_max": param_dicts["x_max"][inp_col],
|
300 |
+
"y_min": param_dicts["y_min"][inp_col],
|
301 |
+
"y_max": param_dicts["y_max"][inp_col]
|
302 |
}
|
303 |
|
304 |
updated_rcs_key = f"{metrics}#@{panel}#@{inp_col}"
|
305 |
if updated_rcs is not None and updated_rcs_key in list(updated_rcs.keys()):
|
306 |
response_curves[inp_col] = updated_rcs[updated_rcs_key]
|
307 |
|
|
|
|
|
|
|
|
|
|
|
308 |
## conversion rates
|
309 |
spend_col = [
|
310 |
_col
|
|
|
331 |
name=inp_col,
|
332 |
dates=dates,
|
333 |
spends=spends,
|
334 |
+
sales= y.copy(),
|
335 |
# conversion_rate = np.mean(list(conv_rates[inp_col].values())),
|
336 |
conversion_rate=conv_rates[inp_col],
|
337 |
+
response_curve_type="hill-eq",
|
338 |
response_curve_params={
|
339 |
+
"Kd": param_dicts["Kd"][inp_col],
|
340 |
+
"n": param_dicts["n"][inp_col],
|
341 |
+
"x_min": param_dicts["x_min"][inp_col],
|
342 |
+
"x_max": param_dicts["x_max"][inp_col],
|
343 |
+
"y_min": param_dicts["y_min"][inp_col],
|
344 |
+
"y_max": param_dicts["y_max"][inp_col]
|
345 |
},
|
346 |
bounds=np.array([-10, 10]),
|
347 |
channel_bounds_min = 10,
|
|
|
402 |
st.session_state["disable_download_button"] = True
|
403 |
|
404 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
def create_channel_summary(scenario):
|
406 |
|
407 |
# Provided data
|
|
|
502 |
return df
|
503 |
|
504 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
|
506 |
def create_contribution_pie():
|
507 |
color_palette = [
|