Spaces:
Sleeping
Sleeping
Pragya Jatav
commited on
Commit
·
ad7f3dc
1
Parent(s):
78401e5
m1
Browse files- Model_Result_Overview.py +4 -4
- Streamlit_functions.py +15 -15
- __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__/utilities.cpython-310.pyc +0 -0
- classes.py +54 -54
- pages/1_Model_Quality.py +12 -12
- pages/2_Scenario_Planner.py +26 -26
- pages/3_Saved_Scenarios.py +8 -8
- response_curves_model_quality.py +17 -17
- response_curves_model_quality_base.py +8 -8
- summary_df.pkl +1 -1
- utilities.py +11 -11
- utilities_with_panel.py +15 -15
Model_Result_Overview.py
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
# else:
|
9 |
# subprocess.check_call([sys.executable, "-m", "conda", "install", package_name, "-y"])
|
10 |
# except subprocess.CalledProcessError as e:
|
11 |
-
# print(f"Failed to install {package_name}: {e}")
|
12 |
|
13 |
# # Example usage
|
14 |
# install_conda_package("plotly-orca", channel="plotly")
|
@@ -69,7 +69,7 @@ def save_table(df,prs):
|
|
69 |
# Add the DataFrame rows to the table
|
70 |
for row_idx, row in df.iterrows():
|
71 |
for col_idx, value in enumerate(row):
|
72 |
-
# # print(value)
|
73 |
if isinstance(value, int):
|
74 |
table.cell(row_idx + 1, col_idx).text = str(value)
|
75 |
|
@@ -141,7 +141,7 @@ def save_ppt_file(fig1,fig2,fig3,fig4,fig6,fig7,figw,start_date,end_date,shares_
|
|
141 |
|
142 |
# prs.save('MMM_Model_Result Overview.pptx')
|
143 |
|
144 |
-
# print("PowerPoint slides created successfully.")
|
145 |
|
146 |
# Save to a BytesIO object
|
147 |
ppt_stream = BytesIO()
|
@@ -154,7 +154,7 @@ def get_random_effects(media_data, panel_col, mdf):
|
|
154 |
random_eff_df = pd.DataFrame(columns=[panel_col, "random_effect"])
|
155 |
|
156 |
for i, market in enumerate(media_data[panel_col].unique()):
|
157 |
-
# # print(i, end='\r')
|
158 |
intercept = mdf.random_effects[market].values[0]
|
159 |
random_eff_df.loc[i, 'random_effect'] = intercept
|
160 |
random_eff_df.loc[i, panel_col] = market
|
|
|
8 |
# else:
|
9 |
# subprocess.check_call([sys.executable, "-m", "conda", "install", package_name, "-y"])
|
10 |
# except subprocess.CalledProcessError as e:
|
11 |
+
# # print(f"Failed to install {package_name}: {e}")
|
12 |
|
13 |
# # Example usage
|
14 |
# install_conda_package("plotly-orca", channel="plotly")
|
|
|
69 |
# Add the DataFrame rows to the table
|
70 |
for row_idx, row in df.iterrows():
|
71 |
for col_idx, value in enumerate(row):
|
72 |
+
# # # print(value)
|
73 |
if isinstance(value, int):
|
74 |
table.cell(row_idx + 1, col_idx).text = str(value)
|
75 |
|
|
|
141 |
|
142 |
# prs.save('MMM_Model_Result Overview.pptx')
|
143 |
|
144 |
+
# # print("PowerPoint slides created successfully.")
|
145 |
|
146 |
# Save to a BytesIO object
|
147 |
ppt_stream = BytesIO()
|
|
|
154 |
random_eff_df = pd.DataFrame(columns=[panel_col, "random_effect"])
|
155 |
|
156 |
for i, market in enumerate(media_data[panel_col].unique()):
|
157 |
+
# # # print(i, end='\r')
|
158 |
intercept = mdf.random_effects[market].values[0]
|
159 |
random_eff_df.loc[i, 'random_effect'] = intercept
|
160 |
random_eff_df.loc[i, panel_col] = market
|
Streamlit_functions.py
CHANGED
@@ -473,8 +473,8 @@ def waterfall2(start_date1,end_date1,start_date2,end_date2):
|
|
473 |
font=dict(size=16),
|
474 |
# align='left'
|
475 |
)
|
476 |
-
# # # print(cur_data)
|
477 |
-
# # # print(prev_data)
|
478 |
# fig.show()
|
479 |
return fig
|
480 |
def waterfall(start_date,end_date,btn_chart):
|
@@ -624,8 +624,8 @@ def waterfall(start_date,end_date,btn_chart):
|
|
624 |
font=dict(size=16),
|
625 |
# align='left'
|
626 |
)
|
627 |
-
# # # print(cur_data)
|
628 |
-
# # # print(prev_data)
|
629 |
# fig.show()
|
630 |
return fig
|
631 |
|
@@ -1084,7 +1084,7 @@ def media_decomp():
|
|
1084 |
|
1085 |
media_cols = media_decomp_df.columns
|
1086 |
for i in range(2,len(media_cols)):
|
1087 |
-
# # # print(media_cols[i])
|
1088 |
cumulative_df[media_cols[i]] = cumulative_df[media_cols[i]] + cumulative_df[media_cols[i-1]]
|
1089 |
# cumulative_df
|
1090 |
|
@@ -1506,16 +1506,16 @@ def scenario_spend_forecasting(delta_df,start_date,end_date):
|
|
1506 |
key_df["Channel_name"] = ["Email","DisplayRetargeting","\xa0Video","BroadcastTV","SocialRetargeting","Connected&OTTTV","SearchBrand","Audio","SocialProspecting","CableTV","DisplayProspecting","SearchNon-brand","DigitalPartners"]
|
1507 |
key_df["Channels"] = ["EMAIL","DISPLAY RETARGETING","VIDEO","BROADCAST TV","SOCIAL RETARGETING","CONNECTED & OTT TV","SEARCH BRAND","AUDIO","SOCIAL PROSPECTING","CABLE TV","DISPLAY PROSPECTING","SEARCH NON-BRAND","DIGITAL PARTNERS"]
|
1508 |
delta_df = delta_df.merge(key_df,on = "Channel_name",how = "inner")
|
1509 |
-
# print(delta_df)
|
1510 |
|
1511 |
data3 = data2.copy()
|
1512 |
for channel in delta_df["Channels"]:
|
1513 |
-
# print(channel)
|
1514 |
delta_percent = delta_df[delta_df["Channels"]==channel]["Delta_percent"].iloc[0]
|
1515 |
-
# print(delta_percent)
|
1516 |
data3[channel] = data3[channel]*(1+delta_percent/100)
|
1517 |
-
# print(data2)
|
1518 |
-
# print(data3)
|
1519 |
|
1520 |
|
1521 |
###### output dataframes
|
@@ -1523,20 +1523,20 @@ def scenario_spend_forecasting(delta_df,start_date,end_date):
|
|
1523 |
|
1524 |
#### percent change dataframe
|
1525 |
delta_df2 = pd.DataFrame(data = delta_df["Delta_percent"].values,index = delta_df["Channels"])
|
1526 |
-
# print(delta_df2)
|
1527 |
output_df1 = (pd.DataFrame(data2.sum()).transpose()).append(pd.DataFrame(data3.sum()).transpose()).append(delta_df2.transpose())
|
1528 |
output_df1.index = ["Last Year Spends", "Forecasted Spends","Spends Change"]
|
1529 |
|
1530 |
|
1531 |
|
1532 |
-
# print(output_df1)
|
1533 |
#
|
1534 |
|
1535 |
|
1536 |
|
1537 |
-
# print (data3)
|
1538 |
# data3 = data2.append(key_df)
|
1539 |
-
# print (data2)
|
1540 |
# cur_data = cur_data[spend_cols]
|
1541 |
# cur_data.columns = channels
|
1542 |
# data1 = pd.DataFrame(cur_data[channels].sum().transpose()).reset_index()
|
@@ -1636,7 +1636,7 @@ def scenario_spend_forecasting2(delta_df,start_date,end_date):
|
|
1636 |
# return "Invalid month number"
|
1637 |
|
1638 |
# data2["Month year"] = data2["Month"].apply(get_month_name) + ' ' +(data2["Date"].dt.year+1).astype(str)
|
1639 |
-
# # # print(data2.columns)
|
1640 |
# data2 = data2[['Month year' ,'BROADCAST TV', 'CABLE TV',
|
1641 |
# 'CONNECTED & OTT TV', 'VIDEO', 'DISPLAY PROSPECTING',
|
1642 |
# 'DISPLAY RETARGETING', 'SOCIAL PROSPECTING', 'SOCIAL RETARGETING',
|
|
|
473 |
font=dict(size=16),
|
474 |
# align='left'
|
475 |
)
|
476 |
+
# # # # print(cur_data)
|
477 |
+
# # # # print(prev_data)
|
478 |
# fig.show()
|
479 |
return fig
|
480 |
def waterfall(start_date,end_date,btn_chart):
|
|
|
624 |
font=dict(size=16),
|
625 |
# align='left'
|
626 |
)
|
627 |
+
# # # # print(cur_data)
|
628 |
+
# # # # print(prev_data)
|
629 |
# fig.show()
|
630 |
return fig
|
631 |
|
|
|
1084 |
|
1085 |
media_cols = media_decomp_df.columns
|
1086 |
for i in range(2,len(media_cols)):
|
1087 |
+
# # # # print(media_cols[i])
|
1088 |
cumulative_df[media_cols[i]] = cumulative_df[media_cols[i]] + cumulative_df[media_cols[i-1]]
|
1089 |
# cumulative_df
|
1090 |
|
|
|
1506 |
key_df["Channel_name"] = ["Email","DisplayRetargeting","\xa0Video","BroadcastTV","SocialRetargeting","Connected&OTTTV","SearchBrand","Audio","SocialProspecting","CableTV","DisplayProspecting","SearchNon-brand","DigitalPartners"]
|
1507 |
key_df["Channels"] = ["EMAIL","DISPLAY RETARGETING","VIDEO","BROADCAST TV","SOCIAL RETARGETING","CONNECTED & OTT TV","SEARCH BRAND","AUDIO","SOCIAL PROSPECTING","CABLE TV","DISPLAY PROSPECTING","SEARCH NON-BRAND","DIGITAL PARTNERS"]
|
1508 |
delta_df = delta_df.merge(key_df,on = "Channel_name",how = "inner")
|
1509 |
+
# # print(delta_df)
|
1510 |
|
1511 |
data3 = data2.copy()
|
1512 |
for channel in delta_df["Channels"]:
|
1513 |
+
# # print(channel)
|
1514 |
delta_percent = delta_df[delta_df["Channels"]==channel]["Delta_percent"].iloc[0]
|
1515 |
+
# # print(delta_percent)
|
1516 |
data3[channel] = data3[channel]*(1+delta_percent/100)
|
1517 |
+
# # print(data2)
|
1518 |
+
# # print(data3)
|
1519 |
|
1520 |
|
1521 |
###### output dataframes
|
|
|
1523 |
|
1524 |
#### percent change dataframe
|
1525 |
delta_df2 = pd.DataFrame(data = delta_df["Delta_percent"].values,index = delta_df["Channels"])
|
1526 |
+
# # print(delta_df2)
|
1527 |
output_df1 = (pd.DataFrame(data2.sum()).transpose()).append(pd.DataFrame(data3.sum()).transpose()).append(delta_df2.transpose())
|
1528 |
output_df1.index = ["Last Year Spends", "Forecasted Spends","Spends Change"]
|
1529 |
|
1530 |
|
1531 |
|
1532 |
+
# # print(output_df1)
|
1533 |
#
|
1534 |
|
1535 |
|
1536 |
|
1537 |
+
# # print (data3)
|
1538 |
# data3 = data2.append(key_df)
|
1539 |
+
# # print (data2)
|
1540 |
# cur_data = cur_data[spend_cols]
|
1541 |
# cur_data.columns = channels
|
1542 |
# data1 = pd.DataFrame(cur_data[channels].sum().transpose()).reset_index()
|
|
|
1636 |
# return "Invalid month number"
|
1637 |
|
1638 |
# data2["Month year"] = data2["Month"].apply(get_month_name) + ' ' +(data2["Date"].dt.year+1).astype(str)
|
1639 |
+
# # # # print(data2.columns)
|
1640 |
# data2 = data2[['Month year' ,'BROADCAST TV', 'CABLE TV',
|
1641 |
# 'CONNECTED & OTT TV', 'VIDEO', 'DISPLAY PROSPECTING',
|
1642 |
# 'DISPLAY RETARGETING', 'SOCIAL PROSPECTING', 'SOCIAL RETARGETING',
|
__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__/utilities.cpython-310.pyc
CHANGED
Binary files a/__pycache__/utilities.cpython-310.pyc and b/__pycache__/utilities.cpython-310.pyc differ
|
|
classes.py
CHANGED
@@ -100,7 +100,7 @@ class Channel:
|
|
100 |
self.modified_total_sales = self.modified_sales.sum()
|
101 |
self.delta_spends = self.modified_total_spends - self.actual_total_spends
|
102 |
self.delta_sales = self.modified_total_sales - self.actual_total_sales
|
103 |
-
# # # print(self.actual_total_spends)
|
104 |
def update_penalty(self, penalty):
|
105 |
self.penalty = penalty
|
106 |
|
@@ -108,25 +108,25 @@ class Channel:
|
|
108 |
return spends_array * total_spends / spends_array.sum()
|
109 |
|
110 |
def modify_spends(self, total_spends):
|
111 |
-
# # # print(total_spends)
|
112 |
self.modified_spends[0] = total_spends
|
113 |
# (
|
114 |
# self.modified_spends * total_spends / self.modified_spends.sum()
|
115 |
# )
|
116 |
-
# # # print("in spends")
|
117 |
-
# # # print(self.modified_spends,self.modified_spends.sum())
|
118 |
|
119 |
def calculate_sales(self):
|
120 |
-
# # # print("in calc_sales")
|
121 |
-
# # # print(self.modified_spends)
|
122 |
return self.response_curve(self.modified_spends)
|
123 |
|
124 |
def hill_equation(x, Kd, n):
|
125 |
return x**n / (Kd**n + x**n)
|
126 |
def response_curve(self, x):
|
127 |
-
# # # print(x)
|
128 |
# if self.penalty:
|
129 |
-
# # # print("in penalty")
|
130 |
# x = np.where(
|
131 |
# x < self.upper_limit,
|
132 |
# x,
|
@@ -134,14 +134,14 @@ class Channel:
|
|
134 |
# )
|
135 |
if self.response_curve_type == "hill-eq":
|
136 |
# dividing_parameter = check_dividing_parameter()
|
137 |
-
# # # print("lalala")
|
138 |
-
# # # # print(self.name)\
|
139 |
-
# # # print(len(x))
|
140 |
-
# # # print("in response curve function")
|
141 |
-
# # # print(x)
|
142 |
if len(x) == 1:
|
143 |
dividing_rate = self.response_curve_params["num_pos_obsv"]
|
144 |
-
# # # print(dividing_rate)
|
145 |
# x = np.sum(x)
|
146 |
else:
|
147 |
dividing_rate = 1
|
@@ -155,14 +155,14 @@ class Channel:
|
|
155 |
x_max= self.response_curve_params["x_max"]
|
156 |
y_min= self.response_curve_params["y_min"]
|
157 |
y_max= self.response_curve_params['y_max']
|
158 |
-
# # # # print(x_min)
|
159 |
-
# # # # print(Kd,n,x_min,x_max,y_min,y_max)
|
160 |
-
# # # # print(np.sum(x)/104)
|
161 |
x_inp = ( x/dividing_rate- x_min) / (x_max - x_min)
|
162 |
-
# # # # print("x",x)
|
163 |
-
# # # # print("x_inp",x_inp)
|
164 |
x_out = x_inp**n / (Kd**n + x_inp**n) #self.hill_equation(x_inp,Kd, n)
|
165 |
-
# # # # print("x_out",x_out)
|
166 |
|
167 |
|
168 |
x_val_inv = (x_out*x_max + (1 - x_out) * x_min)
|
@@ -170,12 +170,12 @@ class Channel:
|
|
170 |
# sales = ((x_max - x_min)*x_out + x_min)*dividing_rate
|
171 |
|
172 |
sales[np.isnan(sales)] = 0
|
173 |
-
# # # # print(sales)
|
174 |
-
# # # # print(np.sum(sales))
|
175 |
-
# # # # print("sales",sales)
|
176 |
-
# # # print("aa")
|
177 |
-
# # # print(sales)
|
178 |
-
# # # print("aa1")
|
179 |
if self.response_curve_type == "s-curve":
|
180 |
if self.power >= 0:
|
181 |
x = x / 10**self.power
|
@@ -292,24 +292,24 @@ class Scenario:
|
|
292 |
|
293 |
def calculate_actual_total_sales(self):
|
294 |
total_actual_sales = 0#self.constant.sum() + self.correction.sum()
|
295 |
-
# # # print("a")
|
296 |
for channel in self.channels.values():
|
297 |
total_actual_sales += channel.actual_total_sales
|
298 |
-
# # # # print(channel.actual_total_sales)
|
299 |
-
# # # # print(total_actual_sales)
|
300 |
return total_actual_sales
|
301 |
|
302 |
def calculate_modified_total_sales(self):
|
303 |
|
304 |
total_modified_sales = 0 #self.constant.sum() + self.correction.sum()
|
305 |
-
# # # print(total_modified_sales)
|
306 |
for channel in self.channels.values():
|
307 |
-
# # # print(channel,channel.modified_total_sales)
|
308 |
total_modified_sales += channel.modified_total_sales
|
309 |
return total_modified_sales
|
310 |
|
311 |
def update(self, channel_name, modified_spends):
|
312 |
-
# # # print("in updtw")
|
313 |
self.channels[channel_name].update(modified_spends)
|
314 |
self.modified_total_sales = self.calculate_modified_total_sales()
|
315 |
self.modified_total_spends = self.calculate_modified_total_spends()
|
@@ -368,7 +368,7 @@ class Scenario:
|
|
368 |
|
369 |
def optimize_spends(self, sales_percent, channels_list, algo="trust-constr"):
|
370 |
num_channels = len(channels_list)
|
371 |
-
# # # # print("%"*100)
|
372 |
desired_sales = self.actual_total_sales * (1 + sales_percent / 100.0)
|
373 |
|
374 |
def constraint(x):
|
@@ -379,7 +379,7 @@ class Scenario:
|
|
379 |
# def calc_overall_bounds(channels_list):
|
380 |
# total_spends=0
|
381 |
# for ch in zip(channels_list):
|
382 |
-
# print(ch)
|
383 |
# total_spends= total_spends+self.channels[ch].actual_total_spends
|
384 |
# return total_spends
|
385 |
|
@@ -393,7 +393,7 @@ class Scenario:
|
|
393 |
lb = (1- int(self.channels[ch].channel_bounds_min) / 100) * self.channels[ch].actual_total_spends
|
394 |
ub = (1+ int(self.channels[ch].channel_bounds_max) / 100) * self.channels[ch].actual_total_spends
|
395 |
bounds.append((lb,ub))
|
396 |
-
# # # # print(self.channels[ch].actual_total_spends)
|
397 |
initial_point = []
|
398 |
for bound in bounds:
|
399 |
initial_point.append(bound[0])
|
@@ -429,11 +429,11 @@ class Scenario:
|
|
429 |
for channel_name in channels_list:
|
430 |
# spends_constraint += self.channels[channel_name].modified_total_spends
|
431 |
spends_constant.append(self.channels[channel_name].conversion_rate)
|
432 |
-
# # # print(spends_constant)
|
433 |
spends_constraint += (
|
434 |
self.channels[channel_name].actual_total_spends+ self.channels[channel_name].delta_spends #st.session_state["total_spends_change_abs_slider_options"]
|
435 |
)
|
436 |
-
# # # print("delta spends",self.channels[channel_name].delta_spends)
|
437 |
# spends_constraint = spends_constraint * (1 + spends_percent / 100)
|
438 |
constraint= LinearConstraint(np.ones((num_channels,)), lb = spends_constraint, ub = spends_constraint)
|
439 |
# constraint = LinearConstraint(
|
@@ -455,8 +455,8 @@ class Scenario:
|
|
455 |
lb = (1- int(_channel_class.channel_bounds_min) / 100) * _channel_class.actual_total_spends
|
456 |
ub = (1+ int(_channel_class.channel_bounds_max) / 100) * _channel_class.actual_total_spends
|
457 |
bounds.append((lb,ub))
|
458 |
-
# # # print("aaaaaa")
|
459 |
-
# # print((_channel_class.channel_bounds_max,_channel_class.channel_bounds_min))
|
460 |
# _channel_class.channel_bounds_min
|
461 |
# _channel_class.channel_bounds_max
|
462 |
def cost_func1(channel,x):
|
@@ -471,29 +471,29 @@ class Scenario:
|
|
471 |
y_max= param_dicts['y_max'][channel]
|
472 |
division_parameter = param_dicts['num_pos_obsv'][channel]
|
473 |
x_inp = ( x/division_parameter- x_min) / (x_max - x_min)
|
474 |
-
# # # print(x_inp)
|
475 |
x_out = x_inp**n / (Kd**n + x_inp**n)
|
476 |
x_val_inv = (x_out*x_max + (1 - x_out) * x_min)
|
477 |
sales = (x_val_inv*y_min/y_max)*division_parameter
|
478 |
if np.isnan(sales):
|
479 |
-
# # # print(sales,channel)
|
480 |
sales = 0
|
481 |
-
# # # print(sales,channel)
|
482 |
return sales
|
483 |
def objective_function(x):
|
484 |
sales = 0
|
485 |
it = 0
|
486 |
for channel_name, modified_spends in zip(channels_list, x):
|
487 |
# sales = sales + cost_func1(channel_name,modified_spends)
|
488 |
-
# print(channel_name, modified_spends,cost_func1(channel_name, modified_spends))
|
489 |
it+=1
|
490 |
self.update(channel_name, modified_spends)
|
491 |
-
# # # print(self.modified_total_sales)
|
492 |
-
# # # print(channel_name, modified_spends)
|
493 |
return -1 * self.modified_total_sales
|
494 |
|
495 |
-
# # # print(bounds)
|
496 |
-
# # # # print("$"*100)
|
497 |
res = minimize(
|
498 |
lambda x: objective_function(x)/1e3,
|
499 |
method="trust-constr",
|
@@ -504,11 +504,11 @@ class Scenario:
|
|
504 |
)
|
505 |
|
506 |
for channel_name, modified_spends in zip(channels_list, res.x):
|
507 |
-
# # # print("aaaaaaaaaaaaaa")
|
508 |
self.update(channel_name, modified_spends)
|
509 |
-
# # # print(channel_name, modified_spends,cost_func1(channel_name, modified_spends))
|
510 |
|
511 |
-
# print(it)
|
512 |
|
513 |
return zip(channels_list, res.x)
|
514 |
|
@@ -533,7 +533,7 @@ class Scenario:
|
|
533 |
|
534 |
# x_vars=[]
|
535 |
# 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]
|
536 |
-
# # # # print(x_vars)
|
537 |
# # x_vars,lower_bounds
|
538 |
|
539 |
# # Define the objective function to minimize
|
@@ -541,8 +541,8 @@ class Scenario:
|
|
541 |
# spends = 0
|
542 |
# i = 0
|
543 |
# for i,c in enumerate(channels_list):
|
544 |
-
# # # # # print(c)
|
545 |
-
# # # # # print(x_vars[i])
|
546 |
# cost = cost + (self.cost_func(c, x_vars[i]))
|
547 |
# spends = spends +x_vars[i]
|
548 |
|
@@ -557,7 +557,7 @@ class Scenario:
|
|
557 |
# m.solve(disp=True)
|
558 |
|
559 |
# for i, var in enumerate(x_vars):
|
560 |
-
# # # # print(f"x{i+1} = {var.value[0]}")
|
561 |
|
562 |
# for channel_name, modified_spends in zip(channels_list, x_vars):
|
563 |
# self.update(channel_name, modified_spends.value[0])
|
|
|
100 |
self.modified_total_sales = self.modified_sales.sum()
|
101 |
self.delta_spends = self.modified_total_spends - self.actual_total_spends
|
102 |
self.delta_sales = self.modified_total_sales - self.actual_total_sales
|
103 |
+
# # # # print(self.actual_total_spends)
|
104 |
def update_penalty(self, penalty):
|
105 |
self.penalty = penalty
|
106 |
|
|
|
108 |
return spends_array * total_spends / spends_array.sum()
|
109 |
|
110 |
def modify_spends(self, total_spends):
|
111 |
+
# # # # print(total_spends)
|
112 |
self.modified_spends[0] = total_spends
|
113 |
# (
|
114 |
# self.modified_spends * total_spends / self.modified_spends.sum()
|
115 |
# )
|
116 |
+
# # # # print("in spends")
|
117 |
+
# # # # print(self.modified_spends,self.modified_spends.sum())
|
118 |
|
119 |
def calculate_sales(self):
|
120 |
+
# # # # print("in calc_sales")
|
121 |
+
# # # # print(self.modified_spends)
|
122 |
return self.response_curve(self.modified_spends)
|
123 |
|
124 |
def hill_equation(x, Kd, n):
|
125 |
return x**n / (Kd**n + x**n)
|
126 |
def response_curve(self, x):
|
127 |
+
# # # # print(x)
|
128 |
# if self.penalty:
|
129 |
+
# # # # print("in penalty")
|
130 |
# x = np.where(
|
131 |
# x < self.upper_limit,
|
132 |
# x,
|
|
|
134 |
# )
|
135 |
if self.response_curve_type == "hill-eq":
|
136 |
# dividing_parameter = check_dividing_parameter()
|
137 |
+
# # # # print("lalala")
|
138 |
+
# # # # # print(self.name)\
|
139 |
+
# # # # print(len(x))
|
140 |
+
# # # # print("in response curve function")
|
141 |
+
# # # # print(x)
|
142 |
if len(x) == 1:
|
143 |
dividing_rate = self.response_curve_params["num_pos_obsv"]
|
144 |
+
# # # # print(dividing_rate)
|
145 |
# x = np.sum(x)
|
146 |
else:
|
147 |
dividing_rate = 1
|
|
|
155 |
x_max= self.response_curve_params["x_max"]
|
156 |
y_min= self.response_curve_params["y_min"]
|
157 |
y_max= self.response_curve_params['y_max']
|
158 |
+
# # # # # print(x_min)
|
159 |
+
# # # # # print(Kd,n,x_min,x_max,y_min,y_max)
|
160 |
+
# # # # # print(np.sum(x)/104)
|
161 |
x_inp = ( x/dividing_rate- x_min) / (x_max - x_min)
|
162 |
+
# # # # # print("x",x)
|
163 |
+
# # # # # print("x_inp",x_inp)
|
164 |
x_out = x_inp**n / (Kd**n + x_inp**n) #self.hill_equation(x_inp,Kd, n)
|
165 |
+
# # # # # print("x_out",x_out)
|
166 |
|
167 |
|
168 |
x_val_inv = (x_out*x_max + (1 - x_out) * x_min)
|
|
|
170 |
# sales = ((x_max - x_min)*x_out + x_min)*dividing_rate
|
171 |
|
172 |
sales[np.isnan(sales)] = 0
|
173 |
+
# # # # # print(sales)
|
174 |
+
# # # # # print(np.sum(sales))
|
175 |
+
# # # # # print("sales",sales)
|
176 |
+
# # # # print("aa")
|
177 |
+
# # # # print(sales)
|
178 |
+
# # # # print("aa1")
|
179 |
if self.response_curve_type == "s-curve":
|
180 |
if self.power >= 0:
|
181 |
x = x / 10**self.power
|
|
|
292 |
|
293 |
def calculate_actual_total_sales(self):
|
294 |
total_actual_sales = 0#self.constant.sum() + self.correction.sum()
|
295 |
+
# # # # print("a")
|
296 |
for channel in self.channels.values():
|
297 |
total_actual_sales += channel.actual_total_sales
|
298 |
+
# # # # # print(channel.actual_total_sales)
|
299 |
+
# # # # # print(total_actual_sales)
|
300 |
return total_actual_sales
|
301 |
|
302 |
def calculate_modified_total_sales(self):
|
303 |
|
304 |
total_modified_sales = 0 #self.constant.sum() + self.correction.sum()
|
305 |
+
# # # # print(total_modified_sales)
|
306 |
for channel in self.channels.values():
|
307 |
+
# # # # print(channel,channel.modified_total_sales)
|
308 |
total_modified_sales += channel.modified_total_sales
|
309 |
return total_modified_sales
|
310 |
|
311 |
def update(self, channel_name, modified_spends):
|
312 |
+
# # # # print("in updtw")
|
313 |
self.channels[channel_name].update(modified_spends)
|
314 |
self.modified_total_sales = self.calculate_modified_total_sales()
|
315 |
self.modified_total_spends = self.calculate_modified_total_spends()
|
|
|
368 |
|
369 |
def optimize_spends(self, sales_percent, channels_list, algo="trust-constr"):
|
370 |
num_channels = len(channels_list)
|
371 |
+
# # # # # print("%"*100)
|
372 |
desired_sales = self.actual_total_sales * (1 + sales_percent / 100.0)
|
373 |
|
374 |
def constraint(x):
|
|
|
379 |
# def calc_overall_bounds(channels_list):
|
380 |
# total_spends=0
|
381 |
# for ch in zip(channels_list):
|
382 |
+
# # print(ch)
|
383 |
# total_spends= total_spends+self.channels[ch].actual_total_spends
|
384 |
# return total_spends
|
385 |
|
|
|
393 |
lb = (1- int(self.channels[ch].channel_bounds_min) / 100) * self.channels[ch].actual_total_spends
|
394 |
ub = (1+ int(self.channels[ch].channel_bounds_max) / 100) * self.channels[ch].actual_total_spends
|
395 |
bounds.append((lb,ub))
|
396 |
+
# # # # # print(self.channels[ch].actual_total_spends)
|
397 |
initial_point = []
|
398 |
for bound in bounds:
|
399 |
initial_point.append(bound[0])
|
|
|
429 |
for channel_name in channels_list:
|
430 |
# spends_constraint += self.channels[channel_name].modified_total_spends
|
431 |
spends_constant.append(self.channels[channel_name].conversion_rate)
|
432 |
+
# # # # print(spends_constant)
|
433 |
spends_constraint += (
|
434 |
self.channels[channel_name].actual_total_spends+ self.channels[channel_name].delta_spends #st.session_state["total_spends_change_abs_slider_options"]
|
435 |
)
|
436 |
+
# # # # print("delta spends",self.channels[channel_name].delta_spends)
|
437 |
# spends_constraint = spends_constraint * (1 + spends_percent / 100)
|
438 |
constraint= LinearConstraint(np.ones((num_channels,)), lb = spends_constraint, ub = spends_constraint)
|
439 |
# constraint = LinearConstraint(
|
|
|
455 |
lb = (1- int(_channel_class.channel_bounds_min) / 100) * _channel_class.actual_total_spends
|
456 |
ub = (1+ int(_channel_class.channel_bounds_max) / 100) * _channel_class.actual_total_spends
|
457 |
bounds.append((lb,ub))
|
458 |
+
# # # # print("aaaaaa")
|
459 |
+
# # # print((_channel_class.channel_bounds_max,_channel_class.channel_bounds_min))
|
460 |
# _channel_class.channel_bounds_min
|
461 |
# _channel_class.channel_bounds_max
|
462 |
def cost_func1(channel,x):
|
|
|
471 |
y_max= param_dicts['y_max'][channel]
|
472 |
division_parameter = param_dicts['num_pos_obsv'][channel]
|
473 |
x_inp = ( x/division_parameter- x_min) / (x_max - x_min)
|
474 |
+
# # # # print(x_inp)
|
475 |
x_out = x_inp**n / (Kd**n + x_inp**n)
|
476 |
x_val_inv = (x_out*x_max + (1 - x_out) * x_min)
|
477 |
sales = (x_val_inv*y_min/y_max)*division_parameter
|
478 |
if np.isnan(sales):
|
479 |
+
# # # # print(sales,channel)
|
480 |
sales = 0
|
481 |
+
# # # # print(sales,channel)
|
482 |
return sales
|
483 |
def objective_function(x):
|
484 |
sales = 0
|
485 |
it = 0
|
486 |
for channel_name, modified_spends in zip(channels_list, x):
|
487 |
# sales = sales + cost_func1(channel_name,modified_spends)
|
488 |
+
# # print(channel_name, modified_spends,cost_func1(channel_name, modified_spends))
|
489 |
it+=1
|
490 |
self.update(channel_name, modified_spends)
|
491 |
+
# # # # print(self.modified_total_sales)
|
492 |
+
# # # # print(channel_name, modified_spends)
|
493 |
return -1 * self.modified_total_sales
|
494 |
|
495 |
+
# # # # print(bounds)
|
496 |
+
# # # # # print("$"*100)
|
497 |
res = minimize(
|
498 |
lambda x: objective_function(x)/1e3,
|
499 |
method="trust-constr",
|
|
|
504 |
)
|
505 |
|
506 |
for channel_name, modified_spends in zip(channels_list, res.x):
|
507 |
+
# # # # print("aaaaaaaaaaaaaa")
|
508 |
self.update(channel_name, modified_spends)
|
509 |
+
# # # # print(channel_name, modified_spends,cost_func1(channel_name, modified_spends))
|
510 |
|
511 |
+
# # print(it)
|
512 |
|
513 |
return zip(channels_list, res.x)
|
514 |
|
|
|
533 |
|
534 |
# x_vars=[]
|
535 |
# 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]
|
536 |
+
# # # # # print(x_vars)
|
537 |
# # x_vars,lower_bounds
|
538 |
|
539 |
# # Define the objective function to minimize
|
|
|
541 |
# spends = 0
|
542 |
# i = 0
|
543 |
# for i,c in enumerate(channels_list):
|
544 |
+
# # # # # # print(c)
|
545 |
+
# # # # # # print(x_vars[i])
|
546 |
# cost = cost + (self.cost_func(c, x_vars[i]))
|
547 |
# spends = spends +x_vars[i]
|
548 |
|
|
|
557 |
# m.solve(disp=True)
|
558 |
|
559 |
# for i, var in enumerate(x_vars):
|
560 |
+
# # # # # print(f"x{i+1} = {var.value[0]}")
|
561 |
|
562 |
# for channel_name, modified_spends in zip(channels_list, x_vars):
|
563 |
# self.update(channel_name, modified_spends.value[0])
|
pages/1_Model_Quality.py
CHANGED
@@ -30,20 +30,20 @@ def save_ppt_file():
|
|
30 |
title_1 = slide_1.shapes.title
|
31 |
title_1.text = "Model Quality"
|
32 |
i = 0
|
33 |
-
# print (i)
|
34 |
# Generate Plotly chart
|
35 |
fig = sf.mmm_model_quality()
|
36 |
|
37 |
# Add the Plotly chart to the slide
|
38 |
add_plotly_chart_to_slide(slide_1, fig, Inches(1), Inches(2), width=Inches(9), height=Inches(4.5))
|
39 |
i = i+1
|
40 |
-
# print (i)
|
41 |
# Slide 2: Media Data Elasticity
|
42 |
slide_2 = prs.slides.add_slide(prs.slide_layouts[5])
|
43 |
title_2 = slide_2.shapes.title
|
44 |
title_2.text = "Media Data Elasticity"
|
45 |
i = i+1
|
46 |
-
# print (i)
|
47 |
# Generate Elasticity chart
|
48 |
media_df = sf.media_data()
|
49 |
fig = sf.elasticity(media_df)
|
@@ -52,17 +52,17 @@ def save_ppt_file():
|
|
52 |
# xaxis=dict(tickangle=-45) # Rotate x-axis labels if needed
|
53 |
)
|
54 |
i = i+1
|
55 |
-
# print (i)
|
56 |
# Add the Plotly chart to the slide
|
57 |
add_plotly_chart_to_slide(slide_2, fig, Inches(1), Inches(2), width=Inches(8), height=Inches(4.5))
|
58 |
i = i+1
|
59 |
-
# print (i)
|
60 |
# Slide 3: Half-Life Analysis
|
61 |
slide_3 = prs.slides.add_slide(prs.slide_layouts[5])
|
62 |
title_3 = slide_3.shapes.title
|
63 |
title_3.text = "Half-Life Analysis"
|
64 |
i = i+1
|
65 |
-
# print (i)
|
66 |
# Generate Half-Life chart
|
67 |
fig = sf.half_life(media_df)
|
68 |
fig.update_layout(
|
@@ -70,11 +70,11 @@ def save_ppt_file():
|
|
70 |
# xaxis=dict(tickangle=-45) # Rotate x-axis labels if needed
|
71 |
)
|
72 |
i = i+1
|
73 |
-
# print (i)
|
74 |
# Add the Plotly chart to the slide
|
75 |
add_plotly_chart_to_slide(slide_3, fig, Inches(1), Inches(2), width=Inches(8), height=Inches(4.5))
|
76 |
i = i+1
|
77 |
-
# print (i)
|
78 |
# Slide 4: Response Curves
|
79 |
|
80 |
# Generate Response Curves chart
|
@@ -98,7 +98,7 @@ def save_ppt_file():
|
|
98 |
title_4 = slide_4.shapes.title
|
99 |
title_4.text = "Response Curves"
|
100 |
i = i+1
|
101 |
-
# print (i)
|
102 |
selected_option = channel_name
|
103 |
selected_option2 = 'View Line Plot'
|
104 |
fig = rc1.response_curves(selected_option, selected_option2)
|
@@ -106,7 +106,7 @@ def save_ppt_file():
|
|
106 |
add_plotly_chart_to_slide(slide_4, fig, Inches(1), Inches(2), width=Inches(6), height=Inches(4.5))
|
107 |
# Save the PowerPoint presentation
|
108 |
# prs.save('MMM_Model_Quality_Presentation.pptx')
|
109 |
-
# # print("PowerPoint slides created successfully.")
|
110 |
|
111 |
# Save to a BytesIO object
|
112 |
ppt_stream = BytesIO()
|
@@ -123,9 +123,9 @@ st.header("Model Quality")
|
|
123 |
|
124 |
st.plotly_chart(sf.mmm_model_quality(),use_container_width=True)
|
125 |
fig = sf.mmm_model_quality()
|
126 |
-
# print("aaa")
|
127 |
# fig.write_image("chart.png")
|
128 |
-
# print("bbb")
|
129 |
|
130 |
media_df = sf.media_data()
|
131 |
# Create two columns for start date and end date input
|
|
|
30 |
title_1 = slide_1.shapes.title
|
31 |
title_1.text = "Model Quality"
|
32 |
i = 0
|
33 |
+
# # print (i)
|
34 |
# Generate Plotly chart
|
35 |
fig = sf.mmm_model_quality()
|
36 |
|
37 |
# Add the Plotly chart to the slide
|
38 |
add_plotly_chart_to_slide(slide_1, fig, Inches(1), Inches(2), width=Inches(9), height=Inches(4.5))
|
39 |
i = i+1
|
40 |
+
# # print (i)
|
41 |
# Slide 2: Media Data Elasticity
|
42 |
slide_2 = prs.slides.add_slide(prs.slide_layouts[5])
|
43 |
title_2 = slide_2.shapes.title
|
44 |
title_2.text = "Media Data Elasticity"
|
45 |
i = i+1
|
46 |
+
# # print (i)
|
47 |
# Generate Elasticity chart
|
48 |
media_df = sf.media_data()
|
49 |
fig = sf.elasticity(media_df)
|
|
|
52 |
# xaxis=dict(tickangle=-45) # Rotate x-axis labels if needed
|
53 |
)
|
54 |
i = i+1
|
55 |
+
# # print (i)
|
56 |
# Add the Plotly chart to the slide
|
57 |
add_plotly_chart_to_slide(slide_2, fig, Inches(1), Inches(2), width=Inches(8), height=Inches(4.5))
|
58 |
i = i+1
|
59 |
+
# # print (i)
|
60 |
# Slide 3: Half-Life Analysis
|
61 |
slide_3 = prs.slides.add_slide(prs.slide_layouts[5])
|
62 |
title_3 = slide_3.shapes.title
|
63 |
title_3.text = "Half-Life Analysis"
|
64 |
i = i+1
|
65 |
+
# # print (i)
|
66 |
# Generate Half-Life chart
|
67 |
fig = sf.half_life(media_df)
|
68 |
fig.update_layout(
|
|
|
70 |
# xaxis=dict(tickangle=-45) # Rotate x-axis labels if needed
|
71 |
)
|
72 |
i = i+1
|
73 |
+
# # print (i)
|
74 |
# Add the Plotly chart to the slide
|
75 |
add_plotly_chart_to_slide(slide_3, fig, Inches(1), Inches(2), width=Inches(8), height=Inches(4.5))
|
76 |
i = i+1
|
77 |
+
# # print (i)
|
78 |
# Slide 4: Response Curves
|
79 |
|
80 |
# Generate Response Curves chart
|
|
|
98 |
title_4 = slide_4.shapes.title
|
99 |
title_4.text = "Response Curves"
|
100 |
i = i+1
|
101 |
+
# # print (i)
|
102 |
selected_option = channel_name
|
103 |
selected_option2 = 'View Line Plot'
|
104 |
fig = rc1.response_curves(selected_option, selected_option2)
|
|
|
106 |
add_plotly_chart_to_slide(slide_4, fig, Inches(1), Inches(2), width=Inches(6), height=Inches(4.5))
|
107 |
# Save the PowerPoint presentation
|
108 |
# prs.save('MMM_Model_Quality_Presentation.pptx')
|
109 |
+
# # # print("PowerPoint slides created successfully.")
|
110 |
|
111 |
# Save to a BytesIO object
|
112 |
ppt_stream = BytesIO()
|
|
|
123 |
|
124 |
st.plotly_chart(sf.mmm_model_quality(),use_container_width=True)
|
125 |
fig = sf.mmm_model_quality()
|
126 |
+
# # print("aaa")
|
127 |
# fig.write_image("chart.png")
|
128 |
+
# # print("bbb")
|
129 |
|
130 |
media_df = sf.media_data()
|
131 |
# Create two columns for start date and end date input
|
pages/2_Scenario_Planner.py
CHANGED
@@ -65,7 +65,7 @@ def save_ppt_file(summary_df_sorted,fig1,fig2,fig3):
|
|
65 |
slide.shapes.add_picture(img_stream, left, top, width, height)
|
66 |
|
67 |
for i in range(0,len(channels_list)):
|
68 |
-
# print(channels_list[i])
|
69 |
slide_1 = prs.slides.add_slide(prs.slide_layouts[6])
|
70 |
fig = rc.response_curves(channels_list[i], summary_df_sorted["Optimized_spend"][channels_list[i]], summary_df_sorted["New_sales"][channels_list[i]])
|
71 |
add_plotly_chart_to_slide(slide_1, fig, Inches(0.1), Inches(0.1), width=Inches(9), height=Inches(7))
|
@@ -163,15 +163,15 @@ def optimize(key, status_placeholder):
|
|
163 |
if key.lower() == "media spends":
|
164 |
with status_placeholder:
|
165 |
with st.spinner("Optimizing"):
|
166 |
-
# # # print(channel_list)
|
167 |
-
# # # print(st.session_state["total_spends_change"])
|
168 |
result = st.session_state["scenario"].optimize(
|
169 |
st.session_state["total_spends_change"], channel_list
|
170 |
# result = st.session_state["scenario"].spends_optimisation(
|
171 |
# st.session_state["total_spends_change"], channel_list
|
172 |
)
|
173 |
-
# print("")
|
174 |
-
# print(list(zip(*result)))
|
175 |
|
176 |
|
177 |
|
@@ -214,7 +214,7 @@ def save_scenario(scenario_name):
|
|
214 |
st.session_state["scenario"]
|
215 |
)
|
216 |
st.session_state["scenario_input"] = ""
|
217 |
-
# # # print(type(st.session_state['saved_scenarios']))
|
218 |
with open("../saved_scenarios.pkl", "wb") as f:
|
219 |
pickle.dump(st.session_state["saved_scenarios"], f)
|
220 |
|
@@ -291,9 +291,9 @@ def update_sales():
|
|
291 |
# def update_all_spends_abs_slider():
|
292 |
# actual_spends = _scenario.actual_total_spends
|
293 |
# if validate_input(st.session_state["total_spends_change_abs_slider"]):
|
294 |
-
# # # print("#" * 100)
|
295 |
-
# # # print(st.session_state["total_spends_change_abs_slider"])C:\Users\PragyaJatav\Downloads\Untitled Folder 2\simulatorAldi\pages\8_Scenario_Planner.py
|
296 |
-
# # # print("#" * 100)
|
297 |
|
298 |
# modified_spends = extract_number_for_string(
|
299 |
# st.session_state["total_spends_change_abs_slider"]
|
@@ -315,8 +315,8 @@ def update_all_spends_abs():
|
|
315 |
# in st.session_state["total_spends_change_abs_slider_options"]
|
316 |
# ):
|
317 |
# st.session_state["allow_spends_update"] = True
|
318 |
-
# print st.session_state["total_spends_change_abs_slider_options"]
|
319 |
-
# print("not allowed")
|
320 |
# else:
|
321 |
# st.session_state["allow_spends_update"] = False
|
322 |
# # st.warning("Invalid Input")
|
@@ -507,7 +507,7 @@ def update_penalty():
|
|
507 |
|
508 |
|
509 |
def reset_scenario(panel_selected, file_selected, updated_rcs):
|
510 |
-
# ## # print(st.session_state['default_scenario_dict'])
|
511 |
# st.session_state['scenario'] = class_from_dict(st.session_state['default_scenario_dict'])
|
512 |
# for channel in st.session_state['scenario'].channels.values():
|
513 |
# st.session_state[channel.name] = float(channel.actual_total_spends * channel.conversion_rate)
|
@@ -646,13 +646,13 @@ def calculate_rgba(
|
|
646 |
|
647 |
|
648 |
def debug_temp(x_test, power, K, b, a, x0):
|
649 |
-
# # # print("*" * 100)
|
650 |
# Calculate the count of bins
|
651 |
count_lower_bin = sum(1 for x in x_test if x <= 2524)
|
652 |
count_center_bin = sum(1 for x in x_test if x > 2524 and x <= 3377)
|
653 |
count_ = sum(1 for x in x_test if x > 3377)
|
654 |
|
655 |
-
# # # print(
|
656 |
# f"""
|
657 |
# lower : {count_lower_bin}
|
658 |
# center : {count_center_bin}
|
@@ -737,14 +737,14 @@ def upload_file_prospects_calc(df):
|
|
737 |
params = pd.read_excel(r"response_curves_parameters.xlsx",index_col = "channel")
|
738 |
param_dicts = {col: params[col].to_dict() for col in params.columns}
|
739 |
df.index = df.channel
|
740 |
-
# # # print(param_dicts)
|
741 |
for col in df.channel:
|
742 |
x = df["Spends"][col]
|
743 |
dividing_rate = 104
|
744 |
# st.write(x)
|
745 |
x_inp = ( x/dividing_rate- param_dicts["x_min"][col]) / (param_dicts["x_max"][col] - param_dicts["x_min"][col])
|
746 |
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)
|
747 |
-
# # # print("x_out",x_out)
|
748 |
|
749 |
|
750 |
x_val_inv = (x_out*param_dicts["x_max"][col] + (1 - x_out) * param_dicts["x_min"][col])
|
@@ -755,7 +755,7 @@ def upload_file_prospects_calc(df):
|
|
755 |
# x_out = x**param_dicts["n"][col]/(param_dicts["Kd"][col]**param_dicts["n"][col]+ x**param_dicts["n"][col])
|
756 |
# x_out_inv = (x_out*(param_dicts["y_max"][col]-param_dicts["y_min"][col])+param_dicts["y_min"][col])*104
|
757 |
df["Prospects"][col] = sales
|
758 |
-
# # # print(df)
|
759 |
return df
|
760 |
|
761 |
|
@@ -1225,7 +1225,7 @@ if auth_status == True:
|
|
1225 |
# ========================== UI ========================== #
|
1226 |
# ======================================================== #
|
1227 |
|
1228 |
-
# # # print(list(st.session_state.keys()))
|
1229 |
main_header = st.columns((2, 2))
|
1230 |
sub_header = st.columns((1, 1, 1, 1))
|
1231 |
_scenario = st.session_state["scenario"]
|
@@ -1770,7 +1770,7 @@ if auth_status == True:
|
|
1770 |
# st.write(channel_spends)
|
1771 |
# st.write(min_value)
|
1772 |
# st.write(max_value)
|
1773 |
-
### # print(st.session_state[channel_name])
|
1774 |
# st.write(_channel_class.channel_bounds_min,channel_bounds_min)
|
1775 |
# st.write(_channel_class.channel_bounds_max,channel_bounds_max)
|
1776 |
_columns_min = st.columns(2)
|
@@ -2043,7 +2043,7 @@ if auth_status == True:
|
|
2043 |
# current_channel_spends,
|
2044 |
# )
|
2045 |
|
2046 |
-
# # # print(st.session_state["acutual_predicted"])
|
2047 |
summary_df = pd.DataFrame(st.session_state["acutual_predicted"])
|
2048 |
# (pd.DataFrame(st.session_state["acutual_predicted"])).to_excel("test.xlsx")
|
2049 |
# st.dataframe(summary_df)
|
@@ -2065,12 +2065,12 @@ if auth_status == True:
|
|
2065 |
a = (summary_df_sorted[summary_df_sorted['Channel_name']== col]).reset_index()['new_efficiency'][0]
|
2066 |
b = (summary_df_sorted[summary_df_sorted['Channel_name']== col]).reset_index()['old_efficiency'][0]
|
2067 |
# st.write(a)
|
2068 |
-
# print(a)
|
2069 |
-
# print(summary_df_sorted['Actual_spend'].sum())
|
2070 |
-
# print(summary_df_sorted['Actual_spend'])
|
2071 |
-
# print(col,summary_df_sorted)
|
2072 |
-
# print(summary_df_sorted['Old_sales'])
|
2073 |
-
# print(col, "old efficiency ", a)
|
2074 |
with bin_placeholder:
|
2075 |
if a> 1:
|
2076 |
fill_color_box = "#6bbf6b"
|
|
|
65 |
slide.shapes.add_picture(img_stream, left, top, width, height)
|
66 |
|
67 |
for i in range(0,len(channels_list)):
|
68 |
+
# # print(channels_list[i])
|
69 |
slide_1 = prs.slides.add_slide(prs.slide_layouts[6])
|
70 |
fig = rc.response_curves(channels_list[i], summary_df_sorted["Optimized_spend"][channels_list[i]], summary_df_sorted["New_sales"][channels_list[i]])
|
71 |
add_plotly_chart_to_slide(slide_1, fig, Inches(0.1), Inches(0.1), width=Inches(9), height=Inches(7))
|
|
|
163 |
if key.lower() == "media spends":
|
164 |
with status_placeholder:
|
165 |
with st.spinner("Optimizing"):
|
166 |
+
# # # # print(channel_list)
|
167 |
+
# # # # print(st.session_state["total_spends_change"])
|
168 |
result = st.session_state["scenario"].optimize(
|
169 |
st.session_state["total_spends_change"], channel_list
|
170 |
# result = st.session_state["scenario"].spends_optimisation(
|
171 |
# st.session_state["total_spends_change"], channel_list
|
172 |
)
|
173 |
+
# # print("")
|
174 |
+
# # print(list(zip(*result)))
|
175 |
|
176 |
|
177 |
|
|
|
214 |
st.session_state["scenario"]
|
215 |
)
|
216 |
st.session_state["scenario_input"] = ""
|
217 |
+
# # # # print(type(st.session_state['saved_scenarios']))
|
218 |
with open("../saved_scenarios.pkl", "wb") as f:
|
219 |
pickle.dump(st.session_state["saved_scenarios"], f)
|
220 |
|
|
|
291 |
# def update_all_spends_abs_slider():
|
292 |
# actual_spends = _scenario.actual_total_spends
|
293 |
# if validate_input(st.session_state["total_spends_change_abs_slider"]):
|
294 |
+
# # # # print("#" * 100)
|
295 |
+
# # # # print(st.session_state["total_spends_change_abs_slider"])C:\Users\PragyaJatav\Downloads\Untitled Folder 2\simulatorAldi\pages\8_Scenario_Planner.py
|
296 |
+
# # # # print("#" * 100)
|
297 |
|
298 |
# modified_spends = extract_number_for_string(
|
299 |
# st.session_state["total_spends_change_abs_slider"]
|
|
|
315 |
# in st.session_state["total_spends_change_abs_slider_options"]
|
316 |
# ):
|
317 |
# st.session_state["allow_spends_update"] = True
|
318 |
+
# # print st.session_state["total_spends_change_abs_slider_options"]
|
319 |
+
# # print("not allowed")
|
320 |
# else:
|
321 |
# st.session_state["allow_spends_update"] = False
|
322 |
# # st.warning("Invalid Input")
|
|
|
507 |
|
508 |
|
509 |
def reset_scenario(panel_selected, file_selected, updated_rcs):
|
510 |
+
# ## # # print(st.session_state['default_scenario_dict'])
|
511 |
# st.session_state['scenario'] = class_from_dict(st.session_state['default_scenario_dict'])
|
512 |
# for channel in st.session_state['scenario'].channels.values():
|
513 |
# st.session_state[channel.name] = float(channel.actual_total_spends * channel.conversion_rate)
|
|
|
646 |
|
647 |
|
648 |
def debug_temp(x_test, power, K, b, a, x0):
|
649 |
+
# # # # print("*" * 100)
|
650 |
# Calculate the count of bins
|
651 |
count_lower_bin = sum(1 for x in x_test if x <= 2524)
|
652 |
count_center_bin = sum(1 for x in x_test if x > 2524 and x <= 3377)
|
653 |
count_ = sum(1 for x in x_test if x > 3377)
|
654 |
|
655 |
+
# # # # print(
|
656 |
# f"""
|
657 |
# lower : {count_lower_bin}
|
658 |
# center : {count_center_bin}
|
|
|
737 |
params = pd.read_excel(r"response_curves_parameters.xlsx",index_col = "channel")
|
738 |
param_dicts = {col: params[col].to_dict() for col in params.columns}
|
739 |
df.index = df.channel
|
740 |
+
# # # # print(param_dicts)
|
741 |
for col in df.channel:
|
742 |
x = df["Spends"][col]
|
743 |
dividing_rate = 104
|
744 |
# st.write(x)
|
745 |
x_inp = ( x/dividing_rate- param_dicts["x_min"][col]) / (param_dicts["x_max"][col] - param_dicts["x_min"][col])
|
746 |
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)
|
747 |
+
# # # # print("x_out",x_out)
|
748 |
|
749 |
|
750 |
x_val_inv = (x_out*param_dicts["x_max"][col] + (1 - x_out) * param_dicts["x_min"][col])
|
|
|
755 |
# x_out = x**param_dicts["n"][col]/(param_dicts["Kd"][col]**param_dicts["n"][col]+ x**param_dicts["n"][col])
|
756 |
# x_out_inv = (x_out*(param_dicts["y_max"][col]-param_dicts["y_min"][col])+param_dicts["y_min"][col])*104
|
757 |
df["Prospects"][col] = sales
|
758 |
+
# # # # print(df)
|
759 |
return df
|
760 |
|
761 |
|
|
|
1225 |
# ========================== UI ========================== #
|
1226 |
# ======================================================== #
|
1227 |
|
1228 |
+
# # # # print(list(st.session_state.keys()))
|
1229 |
main_header = st.columns((2, 2))
|
1230 |
sub_header = st.columns((1, 1, 1, 1))
|
1231 |
_scenario = st.session_state["scenario"]
|
|
|
1770 |
# st.write(channel_spends)
|
1771 |
# st.write(min_value)
|
1772 |
# st.write(max_value)
|
1773 |
+
### # # print(st.session_state[channel_name])
|
1774 |
# st.write(_channel_class.channel_bounds_min,channel_bounds_min)
|
1775 |
# st.write(_channel_class.channel_bounds_max,channel_bounds_max)
|
1776 |
_columns_min = st.columns(2)
|
|
|
2043 |
# current_channel_spends,
|
2044 |
# )
|
2045 |
|
2046 |
+
# # # # print(st.session_state["acutual_predicted"])
|
2047 |
summary_df = pd.DataFrame(st.session_state["acutual_predicted"])
|
2048 |
# (pd.DataFrame(st.session_state["acutual_predicted"])).to_excel("test.xlsx")
|
2049 |
# st.dataframe(summary_df)
|
|
|
2065 |
a = (summary_df_sorted[summary_df_sorted['Channel_name']== col]).reset_index()['new_efficiency'][0]
|
2066 |
b = (summary_df_sorted[summary_df_sorted['Channel_name']== col]).reset_index()['old_efficiency'][0]
|
2067 |
# st.write(a)
|
2068 |
+
# # print(a)
|
2069 |
+
# # print(summary_df_sorted['Actual_spend'].sum())
|
2070 |
+
# # print(summary_df_sorted['Actual_spend'])
|
2071 |
+
# # print(col,summary_df_sorted)
|
2072 |
+
# # print(summary_df_sorted['Old_sales'])
|
2073 |
+
# # print(col, "old efficiency ", a)
|
2074 |
with bin_placeholder:
|
2075 |
if a> 1:
|
2076 |
fill_color_box = "#6bbf6b"
|
pages/3_Saved_Scenarios.py
CHANGED
@@ -40,7 +40,7 @@ def comparison_scenarios_df():
|
|
40 |
summary_df_spend = None
|
41 |
summary_df_prospect = None
|
42 |
# summary_df_efficiency = None
|
43 |
-
#=# # print(scenarios_to_download)
|
44 |
for scenario_name in scenarios_to_compare:
|
45 |
scenario_dict = st.session_state['saved_scenarios'][scenario_name]
|
46 |
_spends = []
|
@@ -125,7 +125,7 @@ def generate_color_gradient(start_color, end_color, num_colors):
|
|
125 |
colortype='hex' # Use 'rgb' to get colors in RGB format
|
126 |
)
|
127 |
|
128 |
-
# print(colors)
|
129 |
# Convert RGB tuples to hex
|
130 |
# hex_colors = [rgb_to_hex(color) for color in colors]
|
131 |
return colors
|
@@ -141,8 +141,8 @@ def generate_color_gradient(start_color, end_color, num_colors):
|
|
141 |
# return custom_colors
|
142 |
|
143 |
def plot_comparison_chart(df,metric,custom_colors):
|
144 |
-
# print(metric)
|
145 |
-
# print(custom_colors)
|
146 |
custom_colors = [
|
147 |
"#4169E1", # Royal Blue
|
148 |
"#ADD8E6", # Light Blue
|
@@ -161,8 +161,8 @@ def plot_comparison_chart(df,metric,custom_colors):
|
|
161 |
# Create traces for each column
|
162 |
traces = []
|
163 |
for i,column in enumerate(df.columns):
|
164 |
-
# print(i)
|
165 |
-
# print(custom_colors[i])
|
166 |
traces.append(go.Bar(
|
167 |
x=df.index,
|
168 |
y=df[column],
|
@@ -418,7 +418,7 @@ def download_scenarios():
|
|
418 |
wb.remove(wb.active)
|
419 |
st.session_state['xlsx_buffer'] = io.BytesIO()
|
420 |
summary_df = None
|
421 |
-
## # print(scenarios_to_download)
|
422 |
for scenario_name in scenarios_to_download:
|
423 |
scenario_dict = st.session_state['saved_scenarios'][scenario_name]
|
424 |
_spends = []
|
@@ -508,7 +508,7 @@ auth_status = st.session_state.get('authentication_status')
|
|
508 |
if auth_status == True:
|
509 |
is_state_initiaized = st.session_state.get('initialized',False)
|
510 |
if not is_state_initiaized:
|
511 |
-
## # print("Scenario page state reloaded")
|
512 |
initialize_data(target_file = "Overview_data_test_panel@#prospects.xlsx")
|
513 |
|
514 |
|
|
|
40 |
summary_df_spend = None
|
41 |
summary_df_prospect = None
|
42 |
# summary_df_efficiency = None
|
43 |
+
#=# # # print(scenarios_to_download)
|
44 |
for scenario_name in scenarios_to_compare:
|
45 |
scenario_dict = st.session_state['saved_scenarios'][scenario_name]
|
46 |
_spends = []
|
|
|
125 |
colortype='hex' # Use 'rgb' to get colors in RGB format
|
126 |
)
|
127 |
|
128 |
+
# # print(colors)
|
129 |
# Convert RGB tuples to hex
|
130 |
# hex_colors = [rgb_to_hex(color) for color in colors]
|
131 |
return colors
|
|
|
141 |
# return custom_colors
|
142 |
|
143 |
def plot_comparison_chart(df,metric,custom_colors):
|
144 |
+
# # print(metric)
|
145 |
+
# # print(custom_colors)
|
146 |
custom_colors = [
|
147 |
"#4169E1", # Royal Blue
|
148 |
"#ADD8E6", # Light Blue
|
|
|
161 |
# Create traces for each column
|
162 |
traces = []
|
163 |
for i,column in enumerate(df.columns):
|
164 |
+
# # print(i)
|
165 |
+
# # print(custom_colors[i])
|
166 |
traces.append(go.Bar(
|
167 |
x=df.index,
|
168 |
y=df[column],
|
|
|
418 |
wb.remove(wb.active)
|
419 |
st.session_state['xlsx_buffer'] = io.BytesIO()
|
420 |
summary_df = None
|
421 |
+
## # # print(scenarios_to_download)
|
422 |
for scenario_name in scenarios_to_download:
|
423 |
scenario_dict = st.session_state['saved_scenarios'][scenario_name]
|
424 |
_spends = []
|
|
|
508 |
if auth_status == True:
|
509 |
is_state_initiaized = st.session_state.get('initialized',False)
|
510 |
if not is_state_initiaized:
|
511 |
+
## # # print("Scenario page state reloaded")
|
512 |
initialize_data(target_file = "Overview_data_test_panel@#prospects.xlsx")
|
513 |
|
514 |
|
response_curves_model_quality.py
CHANGED
@@ -112,7 +112,7 @@ def data_output(channel,X,y,y_fit_inv,x_ext_data,y_fit_inv_ext):
|
|
112 |
for i in range(len(y_fit_inv_ext)):
|
113 |
y_fit_inv_v2_ext.append(y_fit_inv_ext[i][0])
|
114 |
|
115 |
-
# # # print(x_ext_data)
|
116 |
ext_df = pd.DataFrame()
|
117 |
ext_df[f'{channel}_Spends'] = x_ext_data
|
118 |
ext_df[fit_col] = y_fit_inv_v2_ext
|
@@ -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 |
|
@@ -211,7 +211,7 @@ def response_curves(channel,x_modified,y_modified):
|
|
211 |
|
212 |
plotly_data2 = plotly_data.copy()
|
213 |
plotly_data2 = plotly_data[plotly_data[x_col].isnull()==False]
|
214 |
-
# print(plotly_data[plotly_data2['Date'] == plotly_data2['Date'].max()][x_col])
|
215 |
# .dropna(subset=[x_col]).reset_index(inplace = True)
|
216 |
fig.add_trace(go.Scatter(
|
217 |
x=plotly_data[plotly_data2['Date'] == plotly_data2['Date'].max()][x_col],
|
@@ -358,7 +358,7 @@ def data_output(channel,X,y,y_fit_inv,x_ext_data,y_fit_inv_ext):
|
|
358 |
for i in range(len(y_fit_inv_ext)):
|
359 |
y_fit_inv_v2_ext.append(y_fit_inv_ext[i][0])
|
360 |
|
361 |
-
# # # print(x_ext_data)
|
362 |
ext_df = pd.DataFrame()
|
363 |
ext_df[f'{channel}_Spends'] = x_ext_data
|
364 |
ext_df[fit_col] = y_fit_inv_v2_ext
|
@@ -371,7 +371,7 @@ def data_output(channel,X,y,y_fit_inv,x_ext_data,y_fit_inv_ext):
|
|
371 |
|
372 |
ext_df['MAT'] = ["ext","ext","ext"]
|
373 |
|
374 |
-
# # # print(ext_df)
|
375 |
plot_df= plot_df.append(ext_df)
|
376 |
return plot_df
|
377 |
|
@@ -394,7 +394,7 @@ def input_data(df,spend_col,prospect_col):
|
|
394 |
return X,y,x_data,y_data,x_minmax,y_minmax
|
395 |
|
396 |
def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
397 |
-
# # # print(x_max)
|
398 |
x_ext_data = [x_max*1.2,x_max*1.3,x_max*1.5]
|
399 |
# x_ext_data = [1500000,2000000,2500000]
|
400 |
# x_ext_data = [x_max+100,x_max+200,x_max+5000]
|
@@ -403,7 +403,7 @@ def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
|
403 |
for i in range(len(x_scaled)):
|
404 |
x_data.append(x_scaled[i][0])
|
405 |
|
406 |
-
# # # print(x_data)
|
407 |
y_fit = hill_equation(x_data, Kd_fit, n_fit)
|
408 |
y_fit_inv = y_minmax.inverse_transform(np.array(y_fit).reshape(-1,1))
|
409 |
|
@@ -416,8 +416,8 @@ def fit_data(spend_col,prospect_col,channel):
|
|
416 |
|
417 |
X,y,x_data,y_data,x_minmax,y_minmax = input_data(temp_df,spend_col,prospect_col)
|
418 |
y_fit, y_fit_inv, Kd_fit, n_fit = hill_func(x_data,y_data,x_minmax,y_minmax)
|
419 |
-
# # # print('k: ',Kd_fit)
|
420 |
-
# # # print('n: ', n_fit)
|
421 |
|
422 |
##### extend_s_curve
|
423 |
x_ext_data,y_fit_inv_ext= extend_s_curve(temp_df[spend_col].max(),x_minmax,y_minmax, Kd_fit, n_fit)
|
@@ -429,7 +429,7 @@ plotly_data = fit_data(spend_cols[0],prospect_cols[0],channel_cols[0])
|
|
429 |
plotly_data.tail()
|
430 |
|
431 |
for i in range(1,13):
|
432 |
-
# # # print(i)
|
433 |
pdf = fit_data(spend_cols[i],prospect_cols[i],channel_cols[i])
|
434 |
plotly_data = plotly_data.merge(pdf,on = ["Date","MAT"],how = "left")
|
435 |
|
@@ -457,7 +457,7 @@ def response_curves(channel,x_modified,y_modified):
|
|
457 |
))
|
458 |
|
459 |
dividing_parameter = len(plotly_data1[plotly_data1[x_col].isnull()==False])
|
460 |
-
print(dividing_parameter)
|
461 |
plotly_data2 = plotly_data.copy()
|
462 |
plotly_data2 = plotly_data[plotly_data[x_col].isnull()==False]
|
463 |
plotly_data2 = plotly_data2[plotly_data2["MAT"]!="ext"]
|
@@ -473,7 +473,7 @@ def response_curves(channel,x_modified,y_modified):
|
|
473 |
name="Current Spends"
|
474 |
))
|
475 |
|
476 |
-
# print(dividing_parameter)
|
477 |
fig.add_trace(go.Scatter(
|
478 |
x=[x_modified/dividing_parameter],
|
479 |
y=[y_modified/dividing_parameter],
|
|
|
112 |
for i in range(len(y_fit_inv_ext)):
|
113 |
y_fit_inv_v2_ext.append(y_fit_inv_ext[i][0])
|
114 |
|
115 |
+
# # # # print(x_ext_data)
|
116 |
ext_df = pd.DataFrame()
|
117 |
ext_df[f'{channel}_Spends'] = x_ext_data
|
118 |
ext_df[fit_col] = y_fit_inv_v2_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 |
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 |
|
|
|
211 |
|
212 |
plotly_data2 = plotly_data.copy()
|
213 |
plotly_data2 = plotly_data[plotly_data[x_col].isnull()==False]
|
214 |
+
# # print(plotly_data[plotly_data2['Date'] == plotly_data2['Date'].max()][x_col])
|
215 |
# .dropna(subset=[x_col]).reset_index(inplace = True)
|
216 |
fig.add_trace(go.Scatter(
|
217 |
x=plotly_data[plotly_data2['Date'] == plotly_data2['Date'].max()][x_col],
|
|
|
358 |
for i in range(len(y_fit_inv_ext)):
|
359 |
y_fit_inv_v2_ext.append(y_fit_inv_ext[i][0])
|
360 |
|
361 |
+
# # # # print(x_ext_data)
|
362 |
ext_df = pd.DataFrame()
|
363 |
ext_df[f'{channel}_Spends'] = x_ext_data
|
364 |
ext_df[fit_col] = y_fit_inv_v2_ext
|
|
|
371 |
|
372 |
ext_df['MAT'] = ["ext","ext","ext"]
|
373 |
|
374 |
+
# # # # print(ext_df)
|
375 |
plot_df= plot_df.append(ext_df)
|
376 |
return plot_df
|
377 |
|
|
|
394 |
return X,y,x_data,y_data,x_minmax,y_minmax
|
395 |
|
396 |
def extend_s_curve(x_max,x_minmax,y_minmax, Kd_fit, n_fit):
|
397 |
+
# # # # print(x_max)
|
398 |
x_ext_data = [x_max*1.2,x_max*1.3,x_max*1.5]
|
399 |
# x_ext_data = [1500000,2000000,2500000]
|
400 |
# x_ext_data = [x_max+100,x_max+200,x_max+5000]
|
|
|
403 |
for i in range(len(x_scaled)):
|
404 |
x_data.append(x_scaled[i][0])
|
405 |
|
406 |
+
# # # # print(x_data)
|
407 |
y_fit = hill_equation(x_data, Kd_fit, n_fit)
|
408 |
y_fit_inv = y_minmax.inverse_transform(np.array(y_fit).reshape(-1,1))
|
409 |
|
|
|
416 |
|
417 |
X,y,x_data,y_data,x_minmax,y_minmax = input_data(temp_df,spend_col,prospect_col)
|
418 |
y_fit, y_fit_inv, Kd_fit, n_fit = hill_func(x_data,y_data,x_minmax,y_minmax)
|
419 |
+
# # # # print('k: ',Kd_fit)
|
420 |
+
# # # # print('n: ', n_fit)
|
421 |
|
422 |
##### extend_s_curve
|
423 |
x_ext_data,y_fit_inv_ext= extend_s_curve(temp_df[spend_col].max(),x_minmax,y_minmax, Kd_fit, n_fit)
|
|
|
429 |
plotly_data.tail()
|
430 |
|
431 |
for i in range(1,13):
|
432 |
+
# # # # print(i)
|
433 |
pdf = fit_data(spend_cols[i],prospect_cols[i],channel_cols[i])
|
434 |
plotly_data = plotly_data.merge(pdf,on = ["Date","MAT"],how = "left")
|
435 |
|
|
|
457 |
))
|
458 |
|
459 |
dividing_parameter = len(plotly_data1[plotly_data1[x_col].isnull()==False])
|
460 |
+
# print(dividing_parameter)
|
461 |
plotly_data2 = plotly_data.copy()
|
462 |
plotly_data2 = plotly_data[plotly_data[x_col].isnull()==False]
|
463 |
plotly_data2 = plotly_data2[plotly_data2["MAT"]!="ext"]
|
|
|
473 |
name="Current Spends"
|
474 |
))
|
475 |
|
476 |
+
# # print(dividing_parameter)
|
477 |
fig.add_trace(go.Scatter(
|
478 |
x=[x_modified/dividing_parameter],
|
479 |
y=[y_modified/dividing_parameter],
|
response_curves_model_quality_base.py
CHANGED
@@ -111,7 +111,7 @@ def data_output(channel,X,y,y_fit_inv,x_ext_data,y_fit_inv_ext):
|
|
111 |
for i in range(len(y_fit_inv_ext)):
|
112 |
y_fit_inv_v2_ext.append(y_fit_inv_ext[i][0])
|
113 |
|
114 |
-
# # # print(x_ext_data)
|
115 |
ext_df = pd.DataFrame()
|
116 |
ext_df[f'{channel}_Spends'] = x_ext_data
|
117 |
ext_df[f'{channel}_Prospects'] = y_fit_inv_v2_ext
|
@@ -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)
|
@@ -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 |
|
@@ -247,7 +247,7 @@ def response_curves(channel,chart_typ):
|
|
247 |
|
248 |
plotly_data2 = plotly_data[plotly_data[x_col].isnull()==False]
|
249 |
plotly_data2 = plotly_data2[plotly_data2["MAT"]!="ext"]
|
250 |
-
# # print(plotly_data2[x_col].mean(),plotly_data2[y_col].mean())
|
251 |
# import steamlit as st
|
252 |
# st.dataframe()
|
253 |
fig.add_trace(go.Scatter(
|
|
|
111 |
for i in range(len(y_fit_inv_ext)):
|
112 |
y_fit_inv_v2_ext.append(y_fit_inv_ext[i][0])
|
113 |
|
114 |
+
# # # # print(x_ext_data)
|
115 |
ext_df = pd.DataFrame()
|
116 |
ext_df[f'{channel}_Spends'] = x_ext_data
|
117 |
ext_df[f'{channel}_Prospects'] = y_fit_inv_v2_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 |
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 |
|
|
|
247 |
|
248 |
plotly_data2 = plotly_data[plotly_data[x_col].isnull()==False]
|
249 |
plotly_data2 = plotly_data2[plotly_data2["MAT"]!="ext"]
|
250 |
+
# # # print(plotly_data2[x_col].mean(),plotly_data2[y_col].mean())
|
251 |
# import steamlit as st
|
252 |
# st.dataframe()
|
253 |
fig.add_trace(go.Scatter(
|
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:576e0d173ca100c08b5b592f57ac43bc52a32ffaa46cd1b542e5cbe1690f045c
|
3 |
size 1822
|
utilities.py
CHANGED
@@ -211,7 +211,7 @@ def initialize_data(
|
|
211 |
# uopx_conv_rates = {'streaming_impressions' : 0.007,'digital_impressions' : 0.007,'search_clicks' : 0.00719,'tv_impressions' : 0.000173,
|
212 |
# "digital_clicks":0.005,"streaming_clicks":0.004,'streaming_spends':1,"tv_spends":1,"search_spends":1,
|
213 |
# "digital_spends":1}
|
214 |
-
# # # print('State initialized')
|
215 |
|
216 |
excel = pd.read_excel(target_file, sheet_name=None)
|
217 |
|
@@ -305,16 +305,16 @@ def initialize_data(
|
|
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 |
-
# # # print(response_curves)
|
309 |
## conversion rates
|
310 |
spend_col = [
|
311 |
_col
|
312 |
for _col in spend_df.columns
|
313 |
if _col.startswith(inp_col.rsplit("_", 1)[0])
|
314 |
][0]
|
315 |
-
# # # print(spend_col)
|
316 |
-
# # # print('## # printing spendssss')
|
317 |
-
# # # print(spend_col)
|
318 |
conv = (
|
319 |
spend_df.set_index("Week")[spend_col]
|
320 |
/ input_df.set_index("Date")[inp_col].clip(lower=1)
|
@@ -324,10 +324,10 @@ def initialize_data(
|
|
324 |
conv_rates[inp_col] = list(conv.drop("Week", axis=1).mean().to_dict().values())[
|
325 |
0
|
326 |
]
|
327 |
-
# # # print(conv_rates)
|
328 |
-
### # print('Before',conv_rates[inp_col])
|
329 |
# conv_rates[inp_col] = uopx_conv_rates[inp_col]
|
330 |
-
### # print('After',(conv_rates[inp_col]))
|
331 |
|
332 |
channel = Channel(
|
333 |
name=inp_col,
|
@@ -355,13 +355,13 @@ def initialize_data(
|
|
355 |
sales = channel.actual_sales
|
356 |
else:
|
357 |
sales += channel.actual_sales
|
358 |
-
# # # print(actual_output_dic)
|
359 |
other_contributions = (
|
360 |
output_df.drop([*output_cols], axis=1).sum(axis=1, numeric_only=True).values
|
361 |
)
|
362 |
correction = output_df.drop("Date", axis=1).sum(axis=1).values - (sales + other_contributions)
|
363 |
-
# # # print(other_contributions)
|
364 |
-
# # # print(correction)
|
365 |
scenario = Scenario(
|
366 |
name="default",
|
367 |
channels=channels,
|
|
|
211 |
# uopx_conv_rates = {'streaming_impressions' : 0.007,'digital_impressions' : 0.007,'search_clicks' : 0.00719,'tv_impressions' : 0.000173,
|
212 |
# "digital_clicks":0.005,"streaming_clicks":0.004,'streaming_spends':1,"tv_spends":1,"search_spends":1,
|
213 |
# "digital_spends":1}
|
214 |
+
# # # # print('State initialized')
|
215 |
|
216 |
excel = pd.read_excel(target_file, sheet_name=None)
|
217 |
|
|
|
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 |
+
# # # # print(response_curves)
|
309 |
## conversion rates
|
310 |
spend_col = [
|
311 |
_col
|
312 |
for _col in spend_df.columns
|
313 |
if _col.startswith(inp_col.rsplit("_", 1)[0])
|
314 |
][0]
|
315 |
+
# # # # print(spend_col)
|
316 |
+
# # # # print('## # # printing spendssss')
|
317 |
+
# # # # print(spend_col)
|
318 |
conv = (
|
319 |
spend_df.set_index("Week")[spend_col]
|
320 |
/ input_df.set_index("Date")[inp_col].clip(lower=1)
|
|
|
324 |
conv_rates[inp_col] = list(conv.drop("Week", axis=1).mean().to_dict().values())[
|
325 |
0
|
326 |
]
|
327 |
+
# # # # print(conv_rates)
|
328 |
+
### # # print('Before',conv_rates[inp_col])
|
329 |
# conv_rates[inp_col] = uopx_conv_rates[inp_col]
|
330 |
+
### # # print('After',(conv_rates[inp_col]))
|
331 |
|
332 |
channel = Channel(
|
333 |
name=inp_col,
|
|
|
355 |
sales = channel.actual_sales
|
356 |
else:
|
357 |
sales += channel.actual_sales
|
358 |
+
# # # # print(actual_output_dic)
|
359 |
other_contributions = (
|
360 |
output_df.drop([*output_cols], axis=1).sum(axis=1, numeric_only=True).values
|
361 |
)
|
362 |
correction = output_df.drop("Date", axis=1).sum(axis=1).values - (sales + other_contributions)
|
363 |
+
# # # # print(other_contributions)
|
364 |
+
# # # # print(correction)
|
365 |
scenario = Scenario(
|
366 |
name="default",
|
367 |
channels=channels,
|
utilities_with_panel.py
CHANGED
@@ -98,7 +98,7 @@ DATA_PATH = './data'
|
|
98 |
|
99 |
IMAGES_PATH = './data/images_224_224'
|
100 |
|
101 |
-
# New - S# # print 2
|
102 |
if 'bin_dict' not in st.session_state:
|
103 |
|
104 |
with open("data_import.pkl", "rb") as f:
|
@@ -395,7 +395,7 @@ def initialize_data(target_col,selected_markets):
|
|
395 |
# uopx_conv_rates = {'streaming_impressions' : 0.007,'digital_impressions' : 0.007,'search_clicks' : 0.00719,'tv_impressions' : 0.000173,
|
396 |
# "digital_clicks":0.005,"streaming_clicks":0.004,'streaming_spends':1,"tv_spends":1,"search_spends":1,
|
397 |
# "digital_spends":1}
|
398 |
-
## # print('State initialized')
|
399 |
# excel = pd.read_excel("data_test_overview_panel.xlsx",sheet_name=None)
|
400 |
#excel = pd.read_excel("Overview_data_test_panel@#revenue.xlsx" + target_col + ".xlsx",sheet_name=None)
|
401 |
|
@@ -469,7 +469,7 @@ def initialize_data(target_col,selected_markets):
|
|
469 |
for inp_col in channel_list:
|
470 |
#st.write(inp_col)
|
471 |
|
472 |
-
# # New - S# # print 2
|
473 |
# if is_panel:
|
474 |
# input_df1 = input_df.groupby([date_col]).agg({inp_col:'sum'}).reset_index() # aggregate spends on date
|
475 |
# spends = input_df1[inp_col].values
|
@@ -484,7 +484,7 @@ def initialize_data(target_col,selected_markets):
|
|
484 |
|
485 |
|
486 |
# contribution
|
487 |
-
# New - S# # print 2
|
488 |
out_col = [_col for _col in output_df.columns if _col.startswith(inp_col)][0]
|
489 |
if is_panel :
|
490 |
output_df1 = output_df.groupby([date_col]).agg({out_col:'sum'}).reset_index()
|
@@ -505,12 +505,12 @@ def initialize_data(target_col,selected_markets):
|
|
505 |
|
506 |
x = x.astype('float64')
|
507 |
y = y.astype('float64')
|
508 |
-
## # print('## # printing yyyyyyyyy')
|
509 |
-
## # print(inp_col)
|
510 |
-
## # print(x.max())
|
511 |
-
## # print(y.max())
|
512 |
# st.write(y.max(),x.max())
|
513 |
-
# # print(y.max(),x.max())
|
514 |
if y.max()<=0.01:
|
515 |
if x.max()<=0.01 :
|
516 |
st.write("here-here")
|
@@ -539,15 +539,15 @@ def initialize_data(target_col,selected_markets):
|
|
539 |
## conversion rates
|
540 |
spend_col = [_col for _col in spend_df.columns if _col.startswith(inp_col.rsplit('_',1)[0])][0]
|
541 |
|
542 |
-
## # print('## # printing spendssss')
|
543 |
-
## # print(spend_col)
|
544 |
conv = (spend_df.set_index('Week')[spend_col] / input_df.set_index('Date')[inp_col].clip(lower=1)).reset_index()
|
545 |
conv.rename(columns={'index':'Week'},inplace=True)
|
546 |
conv['year'] = conv.Week.dt.year
|
547 |
conv_rates[inp_col] = list(conv.drop('Week',axis=1).mean().to_dict().values())[0]
|
548 |
-
### # print('Before',conv_rates[inp_col])
|
549 |
# conv_rates[inp_col] = uopx_conv_rates[inp_col]
|
550 |
-
### # print('After',(conv_rates[inp_col]))
|
551 |
|
552 |
|
553 |
channel = Channel(name=inp_col,dates=dates,
|
@@ -617,7 +617,7 @@ def initialize_data(target_col,selected_markets):
|
|
617 |
# channel_list = []
|
618 |
# for col in raw_df.columns:
|
619 |
# if 'click' in col.lower() or 'spend' in col.lower() or 'imp' in col.lower():
|
620 |
-
# ### # print(col)
|
621 |
# channel_list.append(col)
|
622 |
# else:
|
623 |
# pass
|
@@ -708,7 +708,7 @@ def create_channel_summary(scenario):
|
|
708 |
if name_mod.lower().endswith(' imp'):
|
709 |
name_mod = name_mod.replace('Imp', ' Impressions')
|
710 |
|
711 |
-
# # print(name_mod, channel.actual_total_spends, channel.conversion_rate,
|
712 |
channel.actual_total_spends * channel.conversion_rate
|
713 |
|
714 |
summary_columns.append(name_mod)
|
|
|
98 |
|
99 |
IMAGES_PATH = './data/images_224_224'
|
100 |
|
101 |
+
# New - S# # # print 2
|
102 |
if 'bin_dict' not in st.session_state:
|
103 |
|
104 |
with open("data_import.pkl", "rb") as f:
|
|
|
395 |
# uopx_conv_rates = {'streaming_impressions' : 0.007,'digital_impressions' : 0.007,'search_clicks' : 0.00719,'tv_impressions' : 0.000173,
|
396 |
# "digital_clicks":0.005,"streaming_clicks":0.004,'streaming_spends':1,"tv_spends":1,"search_spends":1,
|
397 |
# "digital_spends":1}
|
398 |
+
## # # print('State initialized')
|
399 |
# excel = pd.read_excel("data_test_overview_panel.xlsx",sheet_name=None)
|
400 |
#excel = pd.read_excel("Overview_data_test_panel@#revenue.xlsx" + target_col + ".xlsx",sheet_name=None)
|
401 |
|
|
|
469 |
for inp_col in channel_list:
|
470 |
#st.write(inp_col)
|
471 |
|
472 |
+
# # New - S# # # print 2
|
473 |
# if is_panel:
|
474 |
# input_df1 = input_df.groupby([date_col]).agg({inp_col:'sum'}).reset_index() # aggregate spends on date
|
475 |
# spends = input_df1[inp_col].values
|
|
|
484 |
|
485 |
|
486 |
# contribution
|
487 |
+
# New - S# # # print 2
|
488 |
out_col = [_col for _col in output_df.columns if _col.startswith(inp_col)][0]
|
489 |
if is_panel :
|
490 |
output_df1 = output_df.groupby([date_col]).agg({out_col:'sum'}).reset_index()
|
|
|
505 |
|
506 |
x = x.astype('float64')
|
507 |
y = y.astype('float64')
|
508 |
+
## # # print('## # # printing yyyyyyyyy')
|
509 |
+
## # # print(inp_col)
|
510 |
+
## # # print(x.max())
|
511 |
+
## # # print(y.max())
|
512 |
# st.write(y.max(),x.max())
|
513 |
+
# # # print(y.max(),x.max())
|
514 |
if y.max()<=0.01:
|
515 |
if x.max()<=0.01 :
|
516 |
st.write("here-here")
|
|
|
539 |
## conversion rates
|
540 |
spend_col = [_col for _col in spend_df.columns if _col.startswith(inp_col.rsplit('_',1)[0])][0]
|
541 |
|
542 |
+
## # # print('## # # printing spendssss')
|
543 |
+
## # # print(spend_col)
|
544 |
conv = (spend_df.set_index('Week')[spend_col] / input_df.set_index('Date')[inp_col].clip(lower=1)).reset_index()
|
545 |
conv.rename(columns={'index':'Week'},inplace=True)
|
546 |
conv['year'] = conv.Week.dt.year
|
547 |
conv_rates[inp_col] = list(conv.drop('Week',axis=1).mean().to_dict().values())[0]
|
548 |
+
### # # print('Before',conv_rates[inp_col])
|
549 |
# conv_rates[inp_col] = uopx_conv_rates[inp_col]
|
550 |
+
### # # print('After',(conv_rates[inp_col]))
|
551 |
|
552 |
|
553 |
channel = Channel(name=inp_col,dates=dates,
|
|
|
617 |
# channel_list = []
|
618 |
# for col in raw_df.columns:
|
619 |
# if 'click' in col.lower() or 'spend' in col.lower() or 'imp' in col.lower():
|
620 |
+
# ### # # print(col)
|
621 |
# channel_list.append(col)
|
622 |
# else:
|
623 |
# pass
|
|
|
708 |
if name_mod.lower().endswith(' imp'):
|
709 |
name_mod = name_mod.replace('Imp', ' Impressions')
|
710 |
|
711 |
+
# # # print(name_mod, channel.actual_total_spends, channel.conversion_rate,
|
712 |
channel.actual_total_spends * channel.conversion_rate
|
713 |
|
714 |
summary_columns.append(name_mod)
|