Pragya Jatav commited on
Commit
b12e77d
·
1 Parent(s): bca631e
Model_Result_Overview.py CHANGED
@@ -107,287 +107,156 @@ if auth_status:
107
  if not is_state_initiaized:
108
  a=1
109
 
110
- # st.header("")
111
- # st.markdown("<h5 style='font-weight: normal;'>MMM Readout for Selected Period</h5>", unsafe_allow_html=True)
112
- #### Input Select Start and End Date
113
-
114
- # Create two columns for start date and end date input
115
- col1, col2 = st.columns(2)
116
-
117
- # now = datetime.now()
118
- # us_format = now.strftime("%m/%d/%Y")
119
-
120
- # Define the minimum and maximum dates
121
- min_date,max_date = sf.get_date_range()
122
- # st.write(min_date,max_date)
123
- # min_date = datetime(2023, 1, 1)
124
- # max_date = datetime(2024, 12, 31)
125
- default_date1,default_date2 = sf.get_default_dates()
126
- # st.write(default_date1,default_date2)
127
- with col1:
128
- start_date = st.date_input("Start Date: ",value=default_date1,min_value=min_date,
129
- max_value=max_date)
130
-
131
- with col2:
132
- end_date = st.date_input("End Date: ",value = default_date2,min_value=min_date,
133
- max_value=max_date)
134
-
135
- # col1, col2 = st.columns(2)
136
- # with col1:
137
- # fig = sf.pie_spend(start_date,end_date)
138
- # st.plotly_chart(fig,use_container_width=True)
139
- # with col2:
140
- # fig = sf.pie_contributions(start_date,end_date)
141
- # st.plotly_chart(fig,use_container_width=True)
142
- # st.header("Distribution of Spends and Contributions")
143
- fig = sf.pie_charts(start_date,end_date)
144
- st.plotly_chart(fig,use_container_width=True)
145
-
146
- # Dropdown menu options
147
- st.markdown("<h1 style='font-size:28px;'>Change in MMM Estimated Prospect Contributions</h1>", unsafe_allow_html=True)
148
- # st.header("Change in MMM Estimated Prospect Contributions")
149
-
150
-
151
-
152
-
153
- options = [
154
- "Month on Month",
155
- "Year on Year"]
156
- col1, col2 = st.columns(2)
157
- # Create a dropdown menu
158
- with col1:
159
- selected_option = st.selectbox('Select a comparison', options)
160
- with col2:
161
- st.markdown("""</br>""",unsafe_allow_html=True)
162
- if selected_option == "Month on Month" :
163
-
164
- st.markdown(
165
- f"""
166
- <div style="padding: 5px; border-radius: 5px; background-color: #FFFFE0; width: fit-content; display: inline-block;">
167
- <strong> Comparision of current month spends to previous month spends</strong>
168
- </div>
169
- """,
170
- unsafe_allow_html=True
171
- )
172
- else :
173
- st.markdown(
174
- f"""
175
- <div style="padding: 5px; border-radius: 5px; background-color: #FFFFE0; width: fit-content; display: inline-block;">
176
- <strong> Comparision of current month spends to the same month in previous year</strong>
177
- </div>
178
- """,
179
- unsafe_allow_html=True
180
- )
181
- # Waterfall chart
182
-
183
- def get_month_year_list(start_date, end_date):
184
- # Generate a range of dates from start_date to end_date with a monthly frequency
185
- dates = pd.date_range(start=start_date, end=end_date, freq='MS') # 'MS' is month start frequency
186
-
187
- # Extract month and year from each date and create a list of tuples
188
- month_year_list = [(date.month, date.year) for date in dates]
189
-
190
- return month_year_list
191
- def get_start_end_dates(month, year):
192
- start_date = datetime(year, month, 1).date()
193
-
194
- if month == 12:
195
- end_date = datetime(year + 1, 1, 1).date() - timedelta(days=1)
196
- else:
197
- end_date = datetime(year, month + 1, 1).date() - timedelta(days=1)
198
-
199
- return start_date, end_date
200
-
201
- month_year_list = get_month_year_list(start_date, end_date)
202
- dropdown_options = [f"{date.strftime('%B %Y')}" for date in pd.date_range(start=start_date, end=end_date, freq='MS')]
203
- waterfall_option = st.selectbox("Select a month:", dropdown_options)
204
- waterfall_date = datetime.strptime(waterfall_option, "%B %Y")
205
- waterfall_month = waterfall_date.month
206
- waterfall_year = waterfall_date.year
207
- waterfall_start_date, waterfall_end_date = get_start_end_dates(waterfall_month, waterfall_year)
208
-
209
- fig = sf.waterfall(waterfall_start_date,waterfall_end_date,selected_option)
210
- st.plotly_chart(fig,use_container_width=True)
211
-
212
- # Waterfall table
213
- shares_df = sf.shares_df_func(waterfall_start_date,waterfall_end_date)
214
- st.table(sf.waterfall_table_func(shares_df).style.format("{:.0%}"))
215
-
216
- ## Channel Contribution Bar Chart
217
- st.plotly_chart(sf.channel_contribution(start_date,end_date),use_container_width=True)
218
- st.plotly_chart(sf.chanel_spends(start_date,end_date),use_container_width=True)
219
- # Format first three rows in percentage format
220
- # styled_df = sf.shares_table_func(shares_df)
221
- # # styled_df = styled_df.round(0).astype(int)
222
- # styled_df.iloc[:3] = (styled_df.iloc[:3]).astype(int)
223
-
224
- # # Round next two rows to two decimal places
225
- # styled_df.iloc[3:5] = styled_df.iloc[3:5].round(0).astype(str)
226
-
227
- # st.table(styled_df)
228
- st.dataframe(sf.shares_table_func(shares_df),use_container_width=True)
229
-
230
- st.dataframe(sf.eff_table_func(shares_df).style.format({"TOTAL SPEND": "{:,.0f}", "TOTAL SUPPORT": "{:,.0f}", "TOTAL CONTRIBUTION": "{:,.0f}"}),use_container_width=True)
231
-
232
- ### CPP CHART
233
- st.plotly_chart(sf.cpp(start_date,end_date),use_container_width=True)
234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  ### Base decomp CHART
236
- st.plotly_chart(sf.base_decomp(),use_container_width=True)
237
 
238
  ### Media decomp CHART
239
- st.plotly_chart(sf.media_decomp(),use_container_width=True)
240
 
241
-
242
- # st.write(fig.columns)
243
- # st.dataframe(fig)
244
-
245
- # def panel_fetch(file_selected):
246
- # raw_data_mmm_df = pd.read_excel(file_selected, sheet_name="RAW DATA MMM")
247
-
248
- # if "Panel" in raw_data_mmm_df.columns:
249
- # panel = list(set(raw_data_mmm_df["Panel"]))
250
- # else:
251
- # raw_data_mmm_df = None
252
- # panel = None
253
-
254
- # return panel
255
-
256
- # def rerun():
257
- # st.rerun()
258
-
259
- # metrics_selected='prospects'
260
-
261
- # file_selected = (
262
- # f"Overview_data_test_panel@#{metrics_selected}.xlsx"
263
- # )
264
- # panel_list = panel_fetch(file_selected)
265
-
266
- # if "selected_markets" not in st.session_state:
267
- # st.session_state['selected_markets']='DMA1'
268
-
269
-
270
- # st.header('Overview of previous spends')
271
-
272
- # selected_market= st.selectbox(
273
- # "Select Markets",
274
- # ["Total Market"] + panel_list
275
- # )
276
-
277
-
278
-
279
- # initialize_data(target_col,selected_market)
280
- # scenario = st.session_state['scenario']
281
- # raw_df = st.session_state['raw_df']
282
- # st.write(scenario.actual_total_spends)
283
- # st.write(scenario.actual_total_sales)
284
- # columns = st.columns((1,1,3))
285
-
286
- # with columns[0]:
287
- # st.metric(label='Spends', value=format_numbers(float(scenario.actual_total_spends)))
288
- # #### print(f"##################### {scenario.actual_total_sales} ##################")
289
- # with columns[1]:
290
- # st.metric(label=target, value=format_numbers(float(scenario.actual_total_sales),include_indicator=False))
291
-
292
-
293
- # actual_summary_df = create_channel_summary(scenario)
294
- # actual_summary_df['Channel'] = actual_summary_df['Channel'].apply(channel_name_formating)
295
-
296
- # columns = st.columns((2,1))
297
- # #with columns[0]:
298
- # with st.expander('Channel wise overview'):
299
- # st.markdown(actual_summary_df.style.set_table_styles(
300
- # [{
301
- # 'selector': 'th',
302
- # 'props': [('background-color', '#FFFFF')]
303
- # },
304
- # {
305
- # 'selector' : 'tr:nth-child(even)',
306
- # 'props' : [('background-color', '#FFFFF')]
307
- # }]).to_html(), unsafe_allow_html=True)
308
-
309
- # st.markdown("<hr>",unsafe_allow_html=True)
310
- # ##############################
311
-
312
- # st.plotly_chart(create_contribution_pie(scenario),use_container_width=True)
313
- # st.markdown("<hr>",unsafe_allow_html=True)
314
-
315
-
316
- # ################################3
317
- # st.plotly_chart(create_contribuion_stacked_plot(scenario),use_container_width=True)
318
- # st.markdown("<hr>",unsafe_allow_html=True)
319
- # #######################################
320
-
321
- # selected_channel_name = st.selectbox('Channel', st.session_state['channels_list'] + ['non media'], format_func=channel_name_formating)
322
- # selected_channel = scenario.channels.get(selected_channel_name,None)
323
-
324
- # st.plotly_chart(create_channel_spends_sales_plot(selected_channel), use_container_width=True)
325
-
326
- # st.markdown("<hr>",unsafe_allow_html=True)
327
-
328
- # elif auth_status == False:
329
- # st.error('Username/Password is incorrect')
330
-
331
- # if auth_status != True:
332
- # try:
333
- # username_forgot_pw, email_forgot_password, random_password = authenticator.forgot_password('Forgot password')
334
- # if username_forgot_pw:
335
- # st.success('New password sent securely')
336
- # # Random password to be transferred to user securely
337
- # elif username_forgot_pw == False:
338
- # st.error('Username not found')
339
- # except Exception as e:
340
- # st.error(e)
341
- # st.header("")
342
- # st.markdown("<h5 style='font-weight: normal;'>MMM Readout for Selected Period</h5>", unsafe_allow_html=True)
343
- # #### Input Select Start and End Date
344
-
345
- # # Create two columns for start date and end date input
346
- # col1, col2 = st.columns(2)
347
-
348
- # with col1:
349
- # start_date = st.date_input("Start Date: ")
350
-
351
- # with col2:
352
- # end_date = st.date_input("End Date: ")
353
- # # Dropdown menu options
354
- # options = [
355
- # "Month on Month",
356
- # "Year on Year"]
357
- # col1, col2 = st.columns(2)
358
- # # Create a dropdown menu
359
- # with col1:
360
- # selected_option = st.selectbox('Select a comparison', options)
361
- # with col2:
362
- # st.write("")
363
- # # Waterfall chart
364
- # fig = sf.waterfall(start_date,end_date,selected_option)
365
- # st.plotly_chart(fig)
366
-
367
- # # Waterfall table
368
- # shares_df = sf.shares_df_func(start_date,end_date)
369
- # st.table(sf.waterfall_table_func(shares_df).style.format("{:.0%}"))
370
-
371
- # ## Channel Contribution Bar Chart
372
- # st.plotly_chart(sf.channel_contribution(start_date,end_date))
373
- # # Format first three rows in percentage format
374
- # # styled_df = sf.shares_table_func(shares_df)
375
- # # # styled_df = styled_df.round(0).astype(int)
376
- # # styled_df.iloc[:3] = (styled_df.iloc[:3]).astype(int)
377
-
378
- # # # Round next two rows to two decimal places
379
- # # styled_df.iloc[3:5] = styled_df.iloc[3:5].round(0).astype(str)
380
-
381
- # # st.table(styled_df)
382
- # st.dataframe(sf.shares_table_func(shares_df))
383
-
384
- # st.dataframe(sf.eff_table_func(shares_df))
385
-
386
- # ### CPP CHART
387
- # st.plotly_chart(sf.cpp(start_date,end_date))
388
-
389
- # ### Base decomp CHART
390
- # st.plotly_chart(sf.base_decomp())
391
-
392
- # ### Media decomp CHART
393
- # st.plotly_chart(sf.media_decomp())
 
107
  if not is_state_initiaized:
108
  a=1
109
 
110
+ with st.expander("View Channel Wise Spend And Prospect Analysis "):
111
+ # Create two columns for start date and end date input
112
+ col1, col2 = st.columns(2)
113
+ min_date,max_date = sf.get_date_range()
114
+ # st.write(min_date,max_date)
115
+ # min_date = datetime(2023, 1, 1)
116
+ # max_date = datetime(2024, 12, 31)
117
+ default_date1,default_date2 = sf.get_default_dates()
118
+ # st.write(default_date1,default_date2)
119
+ with col1:
120
+ start_date = st.date_input("Start Date: ",value=default_date1,min_value=min_date,
121
+ max_value=max_date)
122
+ with col2:
123
+ end_date = st.date_input("End Date: ",value = default_date2,min_value=min_date,
124
+ max_value=max_date)
125
+ # col1, col2 = st.columns(2)
126
+ # with col1:
127
+ # fig = sf.pie_spend(start_date,end_date)
128
+ # st.plotly_chart(fig,use_container_width=True)
129
+ # with col2:
130
+ # fig = sf.pie_contributions(start_date,end_date)
131
+ # st.plotly_chart(fig,use_container_width=True)
132
+ # st.header("Distribution of Spends and Contributions")
133
+ fig = sf.pie_charts(start_date,end_date)
134
+ st.plotly_chart(fig,use_container_width=True)
135
+
136
+ ## Channel Contribution Bar Chart
137
+ st.plotly_chart(sf.channel_contribution(start_date,end_date),use_container_width=True)
138
+ st.plotly_chart(sf.chanel_spends(start_date,end_date),use_container_width=True)
139
+ # Format first three rows in percentage format
140
+ # styled_df = sf.shares_table_func(shares_df)
141
+ # # styled_df = styled_df.round(0).astype(int)
142
+ # styled_df.iloc[:3] = (styled_df.iloc[:3]).astype(int)
143
+
144
+ # # Round next two rows to two decimal places
145
+ # styled_df.iloc[3:5] = styled_df.iloc[3:5].round(0).astype(str)
146
+
147
+ # st.table(styled_df)
148
+ shares_df = sf.shares_df_func(start_date,end_date)
149
+ st.dataframe(sf.shares_table_func(shares_df),use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
+ st.dataframe(sf.eff_table_func(shares_df).style.format({"TOTAL SPEND": "{:,.0f}", "TOTAL SUPPORT": "{:,.0f}", "TOTAL CONTRIBUTION": "{:,.0f}"}),use_container_width=True)
152
+
153
+ ### CPP CHART
154
+ st.plotly_chart(sf.cpp(start_date,end_date),use_container_width=True)
155
+ data_selection_type = st.radio("Select Input Type",["Compare Monthly Change", "Compare Custom Range"])
156
+ waterfall_start_date,waterfall_end_date = start_date,end_date
157
+ with st.expander("View Change in MMM Estimated Prospect Contributions Analysis"):
158
+ # Dropdown menu options
159
+ st.markdown("<h1 style='font-size:28px;'>Change in MMM Estimated Prospect Contributions</h1>", unsafe_allow_html=True)
160
+ if data_selection_type == "Compare Monthly Change":
161
+ options = [
162
+ "Month on Month",
163
+ "Year on Year"]
164
+ col1, col2 = st.columns(2)
165
+ # Create a dropdown menu
166
+ with col1:
167
+ selected_option = st.selectbox('Select a comparison', options)
168
+ with col2:
169
+ st.markdown("""</br>""",unsafe_allow_html=True)
170
+ if selected_option == "Month on Month" :
171
+
172
+ st.markdown(
173
+ f"""
174
+ <div style="padding: 5px; border-radius: 5px; background-color: #FFFFE0; width: fit-content; display: inline-block;">
175
+ <strong> Comparision of current month spends to previous month spends</strong>
176
+ </div>
177
+ """,
178
+ unsafe_allow_html=True
179
+ )
180
+ else :
181
+ st.markdown(
182
+ f"""
183
+ <div style="padding: 5px; border-radius: 5px; background-color: #FFFFE0; width: fit-content; display: inline-block;">
184
+ <strong> Comparision of current month spends to the same month in previous year</strong>
185
+ </div>
186
+ """,
187
+ unsafe_allow_html=True
188
+ )
189
+ # Waterfall chart
190
+
191
+ def get_month_year_list(start_date, end_date):
192
+ # Generate a range of dates from start_date to end_date with a monthly frequency
193
+ dates = pd.date_range(start=start_date, end=end_date, freq='MS') # 'MS' is month start frequency
194
+
195
+ # Extract month and year from each date and create a list of tuples
196
+ month_year_list = [(date.month, date.year) for date in dates]
197
+
198
+ return month_year_list
199
+ def get_start_end_dates(month, year):
200
+ start_date = datetime(year, month, 1).date()
201
+
202
+ if month == 12:
203
+ end_date = datetime(year + 1, 1, 1).date() - timedelta(days=1)
204
+ else:
205
+ end_date = datetime(year, month + 1, 1).date() - timedelta(days=1)
206
+
207
+ return start_date, end_date
208
+
209
+ month_year_list = get_month_year_list(start_date, end_date)
210
+ dropdown_options = [f"{date.strftime('%B %Y')}" for date in pd.date_range(start=start_date, end=end_date, freq='MS')]
211
+ waterfall_option = st.selectbox("Select a month:", dropdown_options)
212
+ waterfall_date = datetime.strptime(waterfall_option, "%B %Y")
213
+ waterfall_month = waterfall_date.month
214
+ waterfall_year = waterfall_date.year
215
+ waterfall_start_date, waterfall_end_date = get_start_end_dates(waterfall_month, waterfall_year)
216
+ # st.write("abc")
217
+ # figw = sf.waterfall(waterfall_start_date,waterfall_end_date)
218
+ figw= sf.waterfall(waterfall_start_date,waterfall_end_date,selected_option)
219
+ st.plotly_chart(figw,use_container_width=True)
220
+
221
+ elif data_selection_type == "Compare Custom Range":
222
+ col1, col2 = st.columns(2)
223
+ min_date,max_date = sf.get_date_range()
224
+ with col1:
225
+ st.write("Select Time Period 1")
226
+ sc1,sc2 = st.columns(2)
227
+ with sc1:
228
+ waterfall_start_date1 = st.date_input("Start Date 1: ",value=start_date,min_value=min_date,
229
+ max_value=max_date)
230
+ with sc2:
231
+ waterfall_end_date1 = st.date_input("End Date 1: ",value = end_date,min_value=min_date,
232
+ max_value=max_date)
233
+ with col2:
234
+ st.write("Select Time Period 2")
235
+ ec1,ec2 = st.columns(2)
236
+ with ec1:
237
+ waterfall_start_date2 = st.date_input("Start Date 2: ",value=end_date-timedelta(days = -1),min_value=min_date,
238
+ max_value=max_date)
239
+ with ec2:
240
+ diff = min((start_date-end_date).days,-30)
241
+ waterfall_end_date2 = st.date_input("End Date 2: ",value = start_date,min_value=min_date,
242
+ max_value=max_date)
243
+ try:
244
+ figw= sf.waterfall2(waterfall_start_date1,waterfall_end_date1,waterfall_start_date2,waterfall_end_date2)
245
+ st.plotly_chart(figw,use_container_width=True)
246
+ except:
247
+ st.warning("Previous data does not exist")
248
+
249
+
250
+
251
+ # Waterfall table
252
+ # shares_df = sf.shares_df_func(waterfall_start_date,waterfall_end_date)
253
+ st.table(sf.waterfall_table_func(shares_df).style.format("{:.0%}"))
254
+
255
+
256
+ with st.expander("View Decomposition Analysis"):
257
  ### Base decomp CHART
258
+ st.plotly_chart(sf.base_decomp(),use_container_width=True)
259
 
260
  ### Media decomp CHART
261
+ st.plotly_chart(sf.media_decomp(),use_container_width=True)
262
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Overview_data_test_panel@#prospects.xlsx CHANGED
Binary files a/Overview_data_test_panel@#prospects.xlsx and b/Overview_data_test_panel@#prospects.xlsx differ
 
Streamlit_functions.py CHANGED
@@ -254,7 +254,160 @@ def pie_contributions(start_date,end_date):
254
 
255
  # Show the figure
256
  return fig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  def waterfall(start_date,end_date,btn_chart):
259
  # if pd.isnull(start_date) == True :
260
  # start_date = datetime(2024, 1, 28)
@@ -1314,7 +1467,7 @@ def scenario_spend_forecasting2(delta_df,start_date,end_date):
1314
  return "Invalid month number"
1315
 
1316
  data2["Month year"] = data2["Month"].apply(get_month_name) + ' ' +(data2["Date"].dt.year+1).astype(str)
1317
- print(data2.columns)
1318
  data2 = data2[['Month year' ,'BROADCAST TV', 'CABLE TV',
1319
  'CONNECTED & OTT TV', 'VIDEO', 'DISPLAY PROSPECTING',
1320
  'DISPLAY RETARGETING', 'SOCIAL PROSPECTING', 'SOCIAL RETARGETING',
 
254
 
255
  # Show the figure
256
  return fig
257
+ def waterfall2(start_date1,end_date1,start_date2,end_date2):
258
+ btn_chart = "Month on Month"
259
+ # if pd.isnull(start_date) == True :
260
+ # start_date = datetime(2024, 1, 28)
261
+ # if pd.isnull(end_date) == True :
262
+ # end_date = datetime(2024, 2, 24)
263
+ # start_date = datetime.strptime(start_date, "%Y-%m-%d")
264
+ # end_date = datetime.strptime(end_date, "%Y-%m-%d")
265
+ # start_date = start_date.datetime.data
266
+ # end_date = end_date.datetime.data
267
+ start_date1 = pd.to_datetime(start_date1)
268
+ end_date1 = pd.to_datetime(end_date1)
269
+ start_date2 = pd.to_datetime(start_date2)
270
+ end_date2 = pd.to_datetime(end_date2)
271
+
272
+ # if btn_chart == "Month on Month":
273
+ # start_date_prev = start_date +timedelta(weeks=-4)
274
+ # end_date_prev = start_date +timedelta(days=-1)
275
+ # else:
276
+ # start_date_prev = start_date +timedelta(weeks=-52)
277
+ # end_date_prev = start_date_prev +timedelta(weeks=4) +timedelta(days=-1)
278
+
279
+
280
+ if start_date1 < df['Date'].min() :
281
+ return "a"
282
+
283
+ cur_data = df[(df['Date'] >= start_date2) & (df['Date'] <= end_date2)]
284
+ prev_data = df[(df['Date'] >= start_date1) & (df['Date'] <= end_date1)]
285
+
286
+
287
+ # Example data for the waterfall chart
288
+ data = [
289
+ {'label': 'Previous Period', 'value': round(prev_data[contribution_cols].values.sum())},
290
+ {'label': 'Broadcast TV', 'value': round(cur_data['Broadcast TV_Prospects'].sum()-prev_data['Broadcast TV_Prospects'].sum())},
291
+ {'label': 'Cable TV', 'value': round(cur_data['Cable TV_Prospects'].sum()-prev_data['Cable TV_Prospects'].sum())},
292
+ {'label': 'Connected & OTT TV', 'value': round(cur_data['Connected & OTT TV_Prospects'].sum()-prev_data['Connected & OTT TV_Prospects'].sum())},
293
+ {'label': 'Video', 'value': round(cur_data['Video_Prospects'].sum()-prev_data['Video_Prospects'].sum())},
294
+ {'label': 'Display Prospecting', 'value': round(cur_data['Display Prospecting_Prospects'].sum()-prev_data['Display Prospecting_Prospects'].sum())},
295
+ {'label': 'Display Retargeting', 'value': round(cur_data['Display Retargeting_Prospects'].sum()-prev_data['Display Retargeting_Prospects'].sum())},
296
+ {'label': 'Social Prospecting', 'value': round(cur_data['Social Prospecting_Prospects'].sum()-prev_data['Social Prospecting_Prospects'].sum())},
297
+ {'label': 'Social Retargeting', 'value': round(cur_data['Social Retargeting_Prospects'].sum()-prev_data['Social Retargeting_Prospects'].sum())},
298
+ {'label': 'Search Brand', 'value': round(cur_data['Search Brand_Prospects'].sum()-prev_data['Search Brand_Prospects'].sum())},
299
+ {'label': 'Search Non-brand', 'value': round(cur_data['Search Non-brand_Prospects'].sum()-prev_data['Search Non-brand_Prospects'].sum())},
300
+ {'label': 'Digital Partners', 'value': round(cur_data['Digital Partners_Prospects'].sum()-prev_data['Digital Partners_Prospects'].sum())},
301
+ {'label': 'Audio', 'value': round(cur_data['Audio_Prospects'].sum()-prev_data['Audio_Prospects'].sum())},
302
+ {'label': 'Email', 'value': round(cur_data['Email_Prospects'].sum()-prev_data['Email_Prospects'].sum())},
303
+ {'label': 'Current Period', 'value': round(cur_data[contribution_cols].values.sum())}
304
+ ]
305
+
306
+ # Calculate cumulative values for the waterfall chart
307
+ cumulative = [0]
308
+ for i in range(len(data)):
309
+ cumulative.append(cumulative[-1] + data[i]['value'])
310
+
311
+ # Adjusting values to start from zero for both first and last columns
312
+ cumulative[-1] = 0 # Set the last cumulative value to zero
313
+
314
+ # Extracting labels and values
315
+ labels = [item['label'] for item in data]
316
+ values = [item['value'] for item in data]
317
+
318
+ # Plotting the waterfall chart using go.Bar
319
+ bars = []
320
+ for i in range(len(data)):
321
+ color = '#4A88D9' if i == 0 or i == len(data) - 1 else '#DC5537' # Blue for first and last, gray for others
322
+ hover_text = f"<b>{labels[i]}</b><br>Value: {abs(values[i])}"
323
+
324
+ bars.append(go.Bar(
325
+ x=[labels[i]],
326
+ y=[cumulative[i+1] - cumulative[i]],
327
+ base=[cumulative[i]],
328
+ text=[f"{abs(values[i]):,}"],
329
+ textposition='auto',
330
+ hovertemplate=hover_text,
331
+ marker=dict(color=color),
332
+ showlegend=False
333
+ ))
334
 
335
+ # Creating the figure
336
+ fig = go.Figure(data=bars)
337
+
338
+ # Updating layout for black background and gray gridlines
339
+ if btn_chart == "Month on Month":
340
+ fig.update_layout(
341
+ title=f"Change In MMM Estimated Prospect Contribution"
342
+ ,showlegend=False,
343
+ # plot_bgcolor='black',
344
+ # paper_bgcolor='black',
345
+ # font=dict(color='white'), # Changing font color to white for better contrast
346
+ xaxis=dict(
347
+ showgrid=False,
348
+ zeroline=False, # Hiding the x-axis zero line
349
+ ),
350
+ yaxis=dict(
351
+ title="Prospects",
352
+ showgrid=True,
353
+ gridcolor='lightgray',
354
+ griddash='dot', # Setting y-axis gridline color to gray
355
+ zeroline=False, # Hiding the y-axis zero line
356
+ # range=[18000, max(max(cumulative), max(values)) + 1000] # Setting the y-axis range from 19k to slightly above the maximum value
357
+ )
358
+ )
359
+ fig.add_annotation(
360
+ text=f"{start_date2.strftime('%m-%d-%Y')} to {end_date2.strftime('%m-%d-%Y')} vs. {start_date1.strftime('%m-%d-%Y')} To {end_date1.strftime('%m-%d-%Y')}",
361
+ x=0,
362
+ y=1.15,
363
+ xref="x domain",
364
+ yref="y domain",
365
+ showarrow=False,
366
+ font=dict(size=16),
367
+ # align='left'
368
+ )
369
+ # fig.update_xaxes(
370
+ # tickmode="array",
371
+ # # categoryorder="total ascending",
372
+ # tickvals=[f"{abs(values[i])}"],
373
+ # ticktext=[f"{abs(values[i])}"],
374
+ # ticklabelposition="outside",
375
+ # tickfont=dict(color="white"),
376
+ # )
377
+ else :
378
+ fig.update_layout(
379
+ showlegend=False,
380
+ # plot_bgcolor='black',
381
+ # paper_bgcolor='black',
382
+ # font=dict(color='white'), # Changing font color to white for better contrast
383
+ xaxis=dict(
384
+ showgrid=False,
385
+ zeroline=False, # Hiding the x-axis zero line
386
+ ),
387
+ yaxis=dict(
388
+ title="Prospects",
389
+ showgrid=True,
390
+ gridcolor='lightgray',
391
+ griddash='dot', # Setting y-axis gridline color to gray
392
+ zeroline=False, # Hiding the y-axis zero line
393
+ # range=[10000, max(cumulative)+1000] # Setting the y-axis range from 19k to slightly above the maximum value
394
+ )
395
+
396
+ )
397
+ fig.add_annotation(
398
+ 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')}",
399
+ x=0,
400
+ y=1.15,
401
+ xref="x domain",
402
+ yref="y domain",
403
+ showarrow=False,
404
+ font=dict(size=16),
405
+ # align='left'
406
+ )
407
+ # # print(cur_data)
408
+ # # print(prev_data)
409
+ # fig.show()
410
+ return fig
411
  def waterfall(start_date,end_date,btn_chart):
412
  # if pd.isnull(start_date) == True :
413
  # start_date = datetime(2024, 1, 28)
 
1467
  return "Invalid month number"
1468
 
1469
  data2["Month year"] = data2["Month"].apply(get_month_name) + ' ' +(data2["Date"].dt.year+1).astype(str)
1470
+ # print(data2.columns)
1471
  data2 = data2[['Month year' ,'BROADCAST TV', 'CABLE TV',
1472
  'CONNECTED & OTT TV', 'VIDEO', 'DISPLAY PROSPECTING',
1473
  '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__/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
-
104
  def update_penalty(self, penalty):
105
  self.penalty = penalty
106
 
@@ -111,29 +111,39 @@ class Channel:
111
  self.modified_spends = (
112
  self.modified_spends * total_spends / self.modified_spends.sum()
113
  )
 
 
114
 
115
  def calculate_sales(self):
116
- # # print("in calc_sales")
 
117
  return self.response_curve(self.modified_spends)
118
 
119
  def hill_equation(x, Kd, n):
120
  return x**n / (Kd**n + x**n)
121
  def response_curve(self, x):
122
- if self.penalty:
123
- x = np.where(
124
- x < self.upper_limit,
125
- x,
126
- self.upper_limit + (x - self.upper_limit) * self.upper_limit / x,
127
- )
 
 
128
  if self.response_curve_type == "hill-eq":
129
  # dividing_parameter = check_dividing_parameter()
130
- # # print("lalala")
131
- # # print(self.name)
 
 
 
132
  if len(x) == 1:
133
- dividing_rate = 104
 
134
  # x = np.sum(x)
135
  else:
136
  dividing_rate = 1
 
137
  # x = np.sum(x)
138
  # dividing_rate = 104
139
  Kd= self.response_curve_params["Kd"]
@@ -160,6 +170,9 @@ class Channel:
160
  # # print(sales)
161
  # # print(np.sum(sales))
162
  # # print("sales",sales)
 
 
 
163
  if self.response_curve_type == "s-curve":
164
  if self.power >= 0:
165
  x = x / 10**self.power
@@ -260,7 +273,7 @@ class Scenario:
260
  def calculate_modified_total_spends(self):
261
  total_actual_spends = 0.0
262
  for channel in self.channels.values():
263
- total_actual_spends += channel.actual_total_spends * channel.conversion_rate
264
  return total_actual_spends
265
 
266
  def calculate_modified_total_spends(self):
@@ -269,13 +282,14 @@ class Scenario:
269
  # import streamlit as st
270
  # st.write(channel.modified_total_spends )
271
  total_modified_spends += (
272
- channel.modified_total_spends * channel.conversion_rate
 
273
  )
274
  return total_modified_spends
275
 
276
  def calculate_actual_total_sales(self):
277
  total_actual_sales = 0#self.constant.sum() + self.correction.sum()
278
- print("a")
279
  for channel in self.channels.values():
280
  total_actual_sales += channel.actual_total_sales
281
  # # print(channel.actual_total_sales)
@@ -343,16 +357,7 @@ class Scenario:
343
 
344
  # return zip(channels_list, res.x)
345
 
346
- def hill_equation(x, Kd, n):
347
- return x**n / (Kd**n + x**n)
348
-
349
- def cost_func(channel,x):
350
- x_inp = (x/104 - param_dicts["x_min"][channel]) / (param_dicts["x_max"][channel] - param_dicts["x_min"][channel])
351
- # # print(x_inp)
352
- x_out = hill_equation(x_inp, param_dicts["Kd"][channel], param_dicts["n"][channel])
353
- # # print(x_out)
354
- #
355
- return (param_dicts["y_max"][channel] - param_dicts["y_min"][channel])*(x_out + param_dicts["y_min"][channel])*104
356
 
357
 
358
 
@@ -393,10 +398,10 @@ class Scenario:
393
 
394
  for channel_name, modified_spends in zip(channels_list, res.x):
395
  self.update(channel_name, modified_spends)
396
-
397
  return zip(channels_list, res.x)
398
 
399
-
400
 
401
  def optimize(self, spends_percent, channels_list):
402
  # channels_list = self.channels.keys()
@@ -406,17 +411,18 @@ class Scenario:
406
  for channel_name in channels_list:
407
  # spends_constraint += self.channels[channel_name].modified_total_spends
408
  spends_constant.append(self.channels[channel_name].conversion_rate)
 
409
  spends_constraint += (
410
  self.channels[channel_name].actual_total_spends
411
- * self.channels[channel_name].conversion_rate
412
  )
413
  spends_constraint = spends_constraint * (1 + spends_percent / 100)
414
- # constraint= LinearConstraint(np.ones((num_channels,)), lb = spends_constraint, ub = spends_constraint)
415
- constraint = LinearConstraint(
416
- np.array(spends_constant),
417
- lb=spends_constraint,
418
- ub=spends_constraint,
419
- )
420
  bounds = []
421
  old_spends = []
422
  for channel_name in channels_list:
@@ -426,14 +432,41 @@ class Scenario:
426
  (1 + spends_percent / 100)
427
  )
428
  old_spends.append(channel_actual_total_spends)
429
- bounds.append((1+ channel_bounds / 100) * channel_actual_total_spends)
430
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
  def objective_function(x):
 
432
  for channel_name, modified_spends in zip(channels_list, x):
433
- self.update(channel_name, modified_spends)
 
434
  return -1 * self.modified_total_sales
435
 
436
- # # print(bounds)
437
  # # print("$"*100)
438
  res = minimize(
439
  lambda x: objective_function(x) / 1e3,
@@ -441,7 +474,7 @@ class Scenario:
441
  x0=old_spends,
442
  constraints=constraint,
443
  bounds=bounds,
444
- options={"maxiter": int(1e7), "xtol": 50},
445
  )
446
  # res = dual_annealing(
447
  # objective_function,
@@ -454,6 +487,7 @@ class Scenario:
454
  # # print(res)
455
  for channel_name, modified_spends in zip(channels_list, res.x):
456
  self.update(channel_name, modified_spends)
 
457
 
458
  return zip(channels_list, res.x)
459
 
@@ -461,18 +495,7 @@ class Scenario:
461
  def hill_equation(self,x, Kd, n):
462
  return x**n / (Kd**n + x**n)
463
 
464
- def cost_func(self ,channel,x):
465
-
466
- response_curve_params = pd.read_excel("response_curves_parameters.xlsx",index_col = "channel")
467
- param_dicts = {col: response_curve_params[col].to_dict() for col in response_curve_params.columns}
468
-
469
- x_inp = (x/104 - param_dicts["x_min"][channel]) / (param_dicts["x_max"][channel] - param_dicts["x_min"][channel])
470
- # # print(x_inp)
471
- x_out = self.hill_equation(x_inp, param_dicts["Kd"][channel], param_dicts["n"][channel])
472
- # # print(x_out)
473
- #
474
- return (param_dicts["y_max"][channel] - param_dicts["y_min"][channel])*(x_out + param_dicts["y_min"][channel])*104
475
-
476
 
477
  # def spends_optimisation(self, spends_percent,channels_list):
478
  # m = GEKKO(remote=False)
 
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
 
 
111
  self.modified_spends = (
112
  self.modified_spends * total_spends / self.modified_spends.sum()
113
  )
114
+ print("modified spends")
115
+ print(self.modified_spends)
116
 
117
  def calculate_sales(self):
118
+ print("in calc_sales")
119
+ print(self.modified_spends)
120
  return self.response_curve(self.modified_spends)
121
 
122
  def hill_equation(x, Kd, n):
123
  return x**n / (Kd**n + x**n)
124
  def response_curve(self, x):
125
+ print(x)
126
+ # if self.penalty:
127
+ # print("in penalty")
128
+ # x = np.where(
129
+ # x < self.upper_limit,
130
+ # x,
131
+ # self.upper_limit + (x - self.upper_limit) * self.upper_limit / x,
132
+ # )
133
  if self.response_curve_type == "hill-eq":
134
  # dividing_parameter = check_dividing_parameter()
135
+ # print("lalala")
136
+ # # print(self.name)\
137
+ # print(len(x))
138
+ print("in response curve function")
139
+ print(x)
140
  if len(x) == 1:
141
+ dividing_rate = self.response_curve_params["num_pos_obsv"]
142
+ # print(dividing_rate)
143
  # x = np.sum(x)
144
  else:
145
  dividing_rate = 1
146
+ # dividing_rate = self.response_curve_params["num_pos_obsv"]
147
  # x = np.sum(x)
148
  # dividing_rate = 104
149
  Kd= self.response_curve_params["Kd"]
 
170
  # # print(sales)
171
  # # print(np.sum(sales))
172
  # # print("sales",sales)
173
+ print("aa")
174
+ print(sales)
175
+ print("aa1")
176
  if self.response_curve_type == "s-curve":
177
  if self.power >= 0:
178
  x = x / 10**self.power
 
273
  def calculate_modified_total_spends(self):
274
  total_actual_spends = 0.0
275
  for channel in self.channels.values():
276
+ total_actual_spends += channel.actual_total_spends * 1.0
277
  return total_actual_spends
278
 
279
  def calculate_modified_total_spends(self):
 
282
  # import streamlit as st
283
  # st.write(channel.modified_total_spends )
284
  total_modified_spends += (
285
+ channel.modified_total_spends * 1.0
286
+
287
  )
288
  return total_modified_spends
289
 
290
  def calculate_actual_total_sales(self):
291
  total_actual_sales = 0#self.constant.sum() + self.correction.sum()
292
+ # print("a")
293
  for channel in self.channels.values():
294
  total_actual_sales += channel.actual_total_sales
295
  # # print(channel.actual_total_sales)
 
357
 
358
  # return zip(channels_list, res.x)
359
 
360
+
 
 
 
 
 
 
 
 
 
361
 
362
 
363
 
 
398
 
399
  for channel_name, modified_spends in zip(channels_list, res.x):
400
  self.update(channel_name, modified_spends)
401
+
402
  return zip(channels_list, res.x)
403
 
404
+
405
 
406
  def optimize(self, spends_percent, channels_list):
407
  # channels_list = self.channels.keys()
 
411
  for channel_name in channels_list:
412
  # spends_constraint += self.channels[channel_name].modified_total_spends
413
  spends_constant.append(self.channels[channel_name].conversion_rate)
414
+ # print(spends_constant)
415
  spends_constraint += (
416
  self.channels[channel_name].actual_total_spends
417
+ * 1.0
418
  )
419
  spends_constraint = spends_constraint * (1 + spends_percent / 100)
420
+ constraint= LinearConstraint(np.ones((num_channels,)), lb = spends_constraint, ub = spends_constraint)
421
+ # constraint = LinearConstraint(
422
+ # np.array(spends_constant),
423
+ # lb=spends_constraint,
424
+ # ub=spends_constraint,
425
+ # )
426
  bounds = []
427
  old_spends = []
428
  for channel_name in channels_list:
 
432
  (1 + spends_percent / 100)
433
  )
434
  old_spends.append(channel_actual_total_spends)
435
+ # bounds.append((1+ channel_bounds / 100) * channel_actual_total_spends)
436
+ lb = (1- _channel_class.channel_bounds_min / 100) * channel_actual_total_spends
437
+ ub = (1+ _channel_class.channel_bounds_max / 100) * channel_actual_total_spends
438
+ bounds.append((lb,ub))
439
+ # _channel_class.channel_bounds_min
440
+ # _channel_class.channel_bounds_max
441
+ def cost_func1(channel,x):
442
+ response_curve_params = pd.read_excel("response_curves_parameters.xlsx",index_col = "channel")
443
+ param_dicts = {col: response_curve_params[col].to_dict() for col in response_curve_params.columns}
444
+
445
+ Kd= param_dicts["Kd"][channel]
446
+ n= param_dicts["n"][channel]
447
+ x_min= param_dicts["x_min"][channel]
448
+ x_max= param_dicts["x_max"][channel]
449
+ y_min= param_dicts["y_min"][channel]
450
+ y_max= param_dicts['y_max'][channel]
451
+ division_parameter = param_dicts['num_pos_obsv'][channel]
452
+ x_inp = ( x/division_parameter- x_min) / (x_max - x_min)
453
+ # print(x_inp)
454
+ x_out = x_inp**n / (Kd**n + x_inp**n)
455
+ x_val_inv = (x_out*x_max + (1 - x_out) * x_min)
456
+ sales = (x_val_inv*y_min/y_max)*division_parameter
457
+ if np.isnan(sales):
458
+ # print(sales,channel)
459
+ sales = 0
460
+ # print(sales,channel)
461
+ return sales
462
  def objective_function(x):
463
+ modified_total_sales = 0
464
  for channel_name, modified_spends in zip(channels_list, x):
465
+ modified_total_sales = modified_total_sales + cost_func1(channel_name,modified_spends)
466
+ # self.update(channel_name, modified_spends)
467
  return -1 * self.modified_total_sales
468
 
469
+ print(bounds)
470
  # # print("$"*100)
471
  res = minimize(
472
  lambda x: objective_function(x) / 1e3,
 
474
  x0=old_spends,
475
  constraints=constraint,
476
  bounds=bounds,
477
+ options={"maxiter": int(1e7), "xtol": 0.1},
478
  )
479
  # res = dual_annealing(
480
  # objective_function,
 
487
  # # print(res)
488
  for channel_name, modified_spends in zip(channels_list, res.x):
489
  self.update(channel_name, modified_spends)
490
+ print(channel_name, modified_spends,cost_func1(channel_name, modified_spends))
491
 
492
  return zip(channels_list, res.x)
493
 
 
495
  def hill_equation(self,x, Kd, n):
496
  return x**n / (Kd**n + x**n)
497
 
498
+
 
 
 
 
 
 
 
 
 
 
 
499
 
500
  # def spends_optimisation(self, spends_percent,channels_list):
501
  # m = GEKKO(remote=False)
pages/1_Model_Quality.py CHANGED
@@ -16,7 +16,7 @@ st.plotly_chart(sf.mmm_model_quality(),use_container_width=True)
16
 
17
  media_df = sf.media_data()
18
  # Create two columns for start date and end date input
19
- col1, col2 , col3 = st.columns([1,1,1])
20
  df1 = sf.model_metrics_table_func()
21
  st.dataframe(df1,hide_index = True,use_container_width=True)
22
 
 
16
 
17
  media_df = sf.media_data()
18
  # Create two columns for start date and end date input
19
+ col1, col2 , col3 = st.columns([1,0.2,1])
20
  df1 = sf.model_metrics_table_func()
21
  st.dataframe(df1,hide_index = True,use_container_width=True)
22
 
pages/2_Scenario_Planner.py CHANGED
@@ -98,6 +98,9 @@ def optimize(key, status_placeholder):
98
  # result = st.session_state["scenario"].spends_optimisation(
99
  # st.session_state["total_spends_change"], channel_list
100
  )
 
 
 
101
 
102
 
103
  # elif key.lower() == "revenue":
@@ -111,7 +114,7 @@ def optimize(key, status_placeholder):
111
  for channel_name, modified_spends in result:
112
 
113
  st.session_state[channel_name] = numerize(
114
- modified_spends * scenario.channels[channel_name].conversion_rate,
115
  1,
116
  )
117
  prev_spends = (
 
98
  # result = st.session_state["scenario"].spends_optimisation(
99
  # st.session_state["total_spends_change"], channel_list
100
  )
101
+ print("")
102
+ print(list(zip(*result)))
103
+
104
 
105
 
106
  # elif key.lower() == "revenue":
 
114
  for channel_name, modified_spends in result:
115
 
116
  st.session_state[channel_name] = numerize(
117
+ modified_spends * 1.0,
118
  1,
119
  )
120
  prev_spends = (
pages/5_Glossary.py CHANGED
@@ -5,29 +5,32 @@ import streamlit as st
5
  # )
6
 
7
  def glossary_run():
8
- st.subheader("Glossary of MMM Terminology")
9
- st.write("**• Model R-squared \(R\)\:** This is a statistical measure used to determine the percentage of variation in the dependent variable that the independent variables explain collectively. It ranges between 0 and 1, where 1 indicates a perfect fit and 0 indicates no linear relationship. An R2 greater than 0.8 usually indicates a great model fit.")
 
 
10
 
11
- st.write("**• Mean Absolute Percentage Error \(MAPE\):** This is a measure used to determine the accuracy of a predictive model. It calculates the average absolute percentage difference between the actual and predicted values, expressing the result as a percentage to provide a sense of scale for the error.")
12
 
13
- st.write("**• Media & Baseline Elasticity:** It refers to the percentage change in the number of prospects in response to a percentage change in a marketing input \(media channel spends\) or a baseline factor \(like seasonality. macro factors, competitors spending, etc.\). It is a measure of the responsiveness of the number of prospects to changes in the marketing input or the baseline factor")
14
 
15
- st.write("**• Media Half-Life:** This represents the time it takes for a media spend's impact to reduce to half of its initial impact. It is a key aspect of media decay rates, which represent how the effect of advertising diminishes over time \(in weeks\). This term refers to a curve that illustrates the relationship between media spend and the resulting number of prospects.")
16
 
17
- st.write("**• Support:** Equivalent to Impression or Click depending on the media channel.")
18
 
19
- st.write("**• Contribution Share:** Unit is %. It refers to the percentage contribution of a specific marketing channel to the number of prospects. It is calculated by dividing the contribution from a particular channel by the total number of prospects from all media channels \(not including base contributions\).")
20
 
21
- st.write("**• Spend Share:** Unit is %. It refers to the percentage of the total marketing budget that is allocated to a specific marketing channel. It is calculated by dividing the amount spent on a particular channel by the total marketing spend")
22
 
23
- st.write("**• Support Share:** Unit is %. It refers to the percentage of the total media impression that is allocated to a specific marketing channel. It is calculated by dividing support on a particular channel by the total marketing spend")
24
 
25
- st.write("**• Efficiency Index:** it is a metric that measures the cost-effectiveness of a campaign. It is calculated by dividing Contribution Share by Spend Share. An efficiency index above 1 suggests that a channel is more cost-effective than the benchmark, while an efficiency index below 1 suggests it is less cost-effective. The higher the efficiency index, the more cost-effective its channel is")
26
 
27
- st.write("**• Effectiveness Index:** It is a metric that measures how well a particular marketing channel is performing relative to its support/impression. It is calculated by dividing the Contribution Share by the Spend Share for each channel")
28
 
29
- st.write("**• Estimated CPM \(Cost Per Thousand Impressions\):** This is an estimation of the cost for every thousand impressions \(or views\) of its advertisement via that media channel. The default values are generated from historical averages.")
30
-
31
- st.write("**• Estimated CPC \(Cost Per Click\):** This is an estimation of the cost for each time someone clicks on its advertisement via that media channel. The default values are generated from historical averages.")
32
 
 
 
 
33
  glossary_run()
 
5
  # )
6
 
7
  def glossary_run():
8
+ st.header("Glossary")
9
+ with st.expander("Model MMM Terminology"):
10
+ st.subheader("Glossary of MMM Terminology")
11
+ st.write("**• Model R-squared \(R\)\:** This is a statistical measure used to determine the percentage of variation in the dependent variable that the independent variables explain collectively. It ranges between 0 and 1, where 1 indicates a perfect fit and 0 indicates no linear relationship. An R2 greater than 0.8 usually indicates a great model fit.")
12
 
13
+ st.write("**• Mean Absolute Percentage Error \(MAPE\):** This is a measure used to determine the accuracy of a predictive model. It calculates the average absolute percentage difference between the actual and predicted values, expressing the result as a percentage to provide a sense of scale for the error.")
14
 
15
+ st.write("**• Media & Baseline Elasticity:** It refers to the percentage change in the number of prospects in response to a percentage change in a marketing input \(media channel spends\) or a baseline factor \(like seasonality. macro factors, competitors spending, etc.\). It is a measure of the responsiveness of the number of prospects to changes in the marketing input or the baseline factor")
16
 
17
+ st.write("**• Media Half-Life:** This represents the time it takes for a media spend's impact to reduce to half of its initial impact. It is a key aspect of media decay rates, which represent how the effect of advertising diminishes over time \(in weeks\). This term refers to a curve that illustrates the relationship between media spend and the resulting number of prospects.")
18
 
19
+ st.write("**• Support:** Equivalent to Impression or Click depending on the media channel.")
20
 
21
+ st.write("**• Contribution Share:** Unit is %. It refers to the percentage contribution of a specific marketing channel to the number of prospects. It is calculated by dividing the contribution from a particular channel by the total number of prospects from all media channels \(not including base contributions\).")
22
 
23
+ st.write("**• Spend Share:** Unit is %. It refers to the percentage of the total marketing budget that is allocated to a specific marketing channel. It is calculated by dividing the amount spent on a particular channel by the total marketing spend")
24
 
25
+ st.write("**• Support Share:** Unit is %. It refers to the percentage of the total media impression that is allocated to a specific marketing channel. It is calculated by dividing support on a particular channel by the total marketing spend")
26
 
27
+ st.write("**• Efficiency Index:** it is a metric that measures the cost-effectiveness of a campaign. It is calculated by dividing Contribution Share by Spend Share. An efficiency index above 1 suggests that a channel is more cost-effective than the benchmark, while an efficiency index below 1 suggests it is less cost-effective. The higher the efficiency index, the more cost-effective its channel is")
28
 
29
+ st.write("**• Effectiveness Index:** It is a metric that measures how well a particular marketing channel is performing relative to its support/impression. It is calculated by dividing the Contribution Share by the Spend Share for each channel")
30
 
31
+ st.write("**• Estimated CPM \(Cost Per Thousand Impressions\):** This is an estimation of the cost for every thousand impressions \(or views\) of its advertisement via that media channel. The default values are generated from historical averages.")
 
 
32
 
33
+ st.write("**• Estimated CPC \(Cost Per Click\):** This is an estimation of the cost for each time someone clicks on its advertisement via that media channel. The default values are generated from historical averages.")
34
+ with st.expander("Deployment Plan"):
35
+ st.image(r"C:\Users\PragyaJatav\Downloads\image (2).png")
36
  glossary_run()
response_curves_parameters.xlsx CHANGED
Binary files a/response_curves_parameters.xlsx and b/response_curves_parameters.xlsx differ
 
summary_df.pkl CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:ea149846bb9c8341d1a26a5e74dfbfea9df62ce4a7bd05ff07922a9169932a5d
3
  size 1822
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:02f8f23713eadad9c91bae3af6649f9f2e7e2aa8d73fb28986bd48903cb74f38
3
  size 1822
utilities.py CHANGED
@@ -335,7 +335,7 @@ def initialize_data(
335
  spends=spends,
336
  sales= y.copy(),
337
  # conversion_rate = np.mean(list(conv_rates[inp_col].values())),
338
- conversion_rate=conv_rates[inp_col],
339
  response_curve_type="hill-eq",
340
  response_curve_params={
341
  "Kd": param_dicts["Kd"][inp_col],
@@ -343,7 +343,8 @@ def initialize_data(
343
  "x_min": param_dicts["x_min"][inp_col],
344
  "x_max": param_dicts["x_max"][inp_col],
345
  "y_min": param_dicts["y_min"][inp_col],
346
- "y_max": param_dicts["y_max"][inp_col]
 
347
  },
348
  bounds=np.array([-10, 10]),
349
  channel_bounds_min = 10,
@@ -387,7 +388,7 @@ def initialize_data(
387
 
388
  for channel in channels.values():
389
  st.session_state[channel.name] = numerize(
390
- channel.actual_total_spends * channel.conversion_rate, 1
391
  )
392
 
393
  st.session_state["xlsx_buffer"] = io.BytesIO()
 
335
  spends=spends,
336
  sales= y.copy(),
337
  # conversion_rate = np.mean(list(conv_rates[inp_col].values())),
338
+ conversion_rate=1.0 ,#conv_rates[inp_col],
339
  response_curve_type="hill-eq",
340
  response_curve_params={
341
  "Kd": param_dicts["Kd"][inp_col],
 
343
  "x_min": param_dicts["x_min"][inp_col],
344
  "x_max": param_dicts["x_max"][inp_col],
345
  "y_min": param_dicts["y_min"][inp_col],
346
+ "y_max": param_dicts["y_max"][inp_col],
347
+ "num_pos_obsv":param_dicts["num_pos_obsv"][inp_col]
348
  },
349
  bounds=np.array([-10, 10]),
350
  channel_bounds_min = 10,
 
388
 
389
  for channel in channels.values():
390
  st.session_state[channel.name] = numerize(
391
+ channel.actual_total_spends * 1.0, 1
392
  )
393
 
394
  st.session_state["xlsx_buffer"] = io.BytesIO()