Spaces:
Sleeping
Sleeping
import streamlit as st | |
from numerize.numerize import numerize | |
import pandas as pd | |
from utilities import (format_numbers,decimal_formater, | |
load_local_css,set_header, | |
initialize_data, | |
load_authenticator) | |
import pickle | |
import streamlit_authenticator as stauth | |
import yaml | |
from yaml import SafeLoader | |
from classes import class_from_dict | |
import plotly.express as px | |
import numpy as np | |
import plotly.graph_objects as go | |
import pandas as pd | |
from plotly.subplots import make_subplots | |
def format_number(x): | |
if x >= 1_000_000: | |
return f'{x / 1_000_000:.2f}M' | |
elif x >= 1_000: | |
return f'{x / 1_000:.2f}K' | |
else: | |
return f'{x:.2f}' | |
def summary_plot(data, x, y, title, text_column, color, format_as_percent=False, format_as_decimal=False): | |
fig = px.bar(data, x=x, y=y, orientation='h', | |
title=title, text=text_column, color=color) | |
fig.update_layout(showlegend=False) | |
data[text_column] = pd.to_numeric(data[text_column], errors='coerce') | |
# Update the format of the displayed text based on the chosen format | |
if format_as_percent: | |
fig.update_traces(texttemplate='%{text:.0%}', textposition='outside', hovertemplate='%{x:.0%}') | |
elif format_as_decimal: | |
fig.update_traces(texttemplate='%{text:.2f}', textposition='outside', hovertemplate='%{x:.2f}') | |
else: | |
fig.update_traces(texttemplate='%{text:.2s}', textposition='outside', hovertemplate='%{x:.2s}') | |
fig.update_layout(xaxis_title=x, yaxis_title='Channel Name', showlegend=False) | |
return fig | |
def stacked_summary_plot(data, x, y, title, text_column, color_column, stack_column=None, format_as_percent=False, format_as_decimal=False): | |
fig = px.bar(data, x=x, y=y, orientation='h', | |
title=title, text=text_column, color=color_column, facet_col=stack_column) | |
fig.update_layout(showlegend=False) | |
data[text_column] = pd.to_numeric(data[text_column], errors='coerce') | |
# Update the format of the displayed text based on the chosen format | |
if format_as_percent: | |
fig.update_traces(texttemplate='%{text:.0%}', textposition='outside', hovertemplate='%{x:.0%}') | |
elif format_as_decimal: | |
fig.update_traces(texttemplate='%{text:.2f}', textposition='outside', hovertemplate='%{x:.2f}') | |
else: | |
fig.update_traces(texttemplate='%{text:.2s}', textposition='outside', hovertemplate='%{x:.2s}') | |
fig.update_layout(xaxis_title=x, yaxis_title='', showlegend=False) | |
return fig | |
def funnel_plot(data, x, y, title, text_column, color_column, format_as_percent=False, format_as_decimal=False): | |
data[text_column] = pd.to_numeric(data[text_column], errors='coerce') | |
# Round the numeric values in the text column to two decimal points | |
data[text_column] = data[text_column].round(2) | |
# Create a color map for categorical data | |
color_map = {category: f'rgb({i * 30 % 255},{i * 50 % 255},{i * 70 % 255})' for i, category in enumerate(data[color_column].unique())} | |
fig = go.Figure(go.Funnel( | |
y=data[y], | |
x=data[x], | |
text=data[text_column], | |
marker=dict(color=data[color_column].map(color_map)), | |
textinfo="value", | |
hoverinfo='y+x+text' | |
)) | |
# Update the format of the displayed text based on the chosen format | |
if format_as_percent: | |
fig.update_layout(title=title, funnelmode="percent") | |
elif format_as_decimal: | |
fig.update_layout(title=title, funnelmode="overlay") | |
else: | |
fig.update_layout(title=title, funnelmode="group") | |
return fig | |
st.set_page_config(layout='wide') | |
load_local_css('styles.css') | |
set_header() | |
# for k, v in st.session_state.items(): | |
# if k not in ['logout', 'login','config'] and not k.startswith('FormSubmitter'): | |
# st.session_state[k] = v | |
st.empty() | |
st.header('Model Result Analysis') | |
spends_data=pd.read_excel('Overview_data_test.xlsx') | |
with open('summary_df.pkl', 'rb') as file: | |
summary_df_sorted = pickle.load(file) | |
#st.write(summary_df_sorted) | |
selected_scenario= st.selectbox('Select Saved Scenarios',['S1','S2']) | |
summary_df_sorted=summary_df_sorted.sort_values(by=['Optimized_spend'],ascending=False) | |
st.header('Optimized Spends Overview') | |
___columns=st.columns(3) | |
with ___columns[2]: | |
fig=summary_plot(summary_df_sorted, x='Delta_percent', y='Channel_name', title='Delta', text_column='Delta_percent',color='Channel_name') | |
st.plotly_chart(fig,use_container_width=True) | |
with ___columns[0]: | |
fig=summary_plot(summary_df_sorted, x='Actual_spend', y='Channel_name', title='Actual Spend', text_column='Actual_spend',color='Channel_name') | |
st.plotly_chart(fig,use_container_width=True) | |
with ___columns[1]: | |
fig=summary_plot(summary_df_sorted, x='Optimized_spend', y='Channel_name', title='Planned Spend', text_column='Optimized_spend',color='Channel_name') | |
st.plotly_chart(fig,use_container_width=False) | |
st.header(' Budget Allocation') | |
summary_df_sorted['Perc_alloted']=np.round(summary_df_sorted['Optimized_spend']/summary_df_sorted['Optimized_spend'].sum(),2) | |
columns2=st.columns(2) | |
with columns2[0]: | |
fig=summary_plot(summary_df_sorted, x='Optimized_spend', y='Channel_name', title='Planned Spend', text_column='Optimized_spend',color='Channel_name') | |
st.plotly_chart(fig,use_container_width=True) | |
with columns2[1]: | |
fig=summary_plot(summary_df_sorted, x='Perc_alloted', y='Channel_name', title='% Split', text_column='Perc_alloted',color='Channel_name',format_as_percent=True) | |
st.plotly_chart(fig,use_container_width=True) | |
if 'raw_data' not in st.session_state: | |
st.session_state['raw_data']=pd.read_excel('raw_data_nov7_combined1.xlsx') | |
st.session_state['raw_data']=st.session_state['raw_data'][st.session_state['raw_data']['MediaChannelName'].isin(summary_df_sorted['Channel_name'].unique())] | |
st.session_state['raw_data']=st.session_state['raw_data'][st.session_state['raw_data']['Date'].isin(spends_data["Date"].unique())] | |
#st.write(st.session_state['raw_data']['ResponseMetricName']) | |
# st.write(st.session_state['raw_data']) | |
st.header('Response Forecast Overview') | |
raw_data=st.session_state['raw_data'] | |
effectiveness_overall=raw_data.groupby('ResponseMetricName').agg({'ResponseMetricValue': 'sum'}).reset_index() | |
effectiveness_overall['Efficiency']=effectiveness_overall['ResponseMetricValue'].map(lambda x: x/raw_data['Media Spend'].sum() ) | |
# st.write(effectiveness_overall) | |
columns6=st.columns(3) | |
effectiveness_overall.sort_values(by=['ResponseMetricValue'],ascending=False,inplace=True) | |
effectiveness_overall=np.round(effectiveness_overall,2) | |
effectiveness_overall['ResponseMetric'] = effectiveness_overall['ResponseMetricName'].apply(lambda x: 'BAU' if 'BAU' in x else ('Gamified' if 'Gamified' in x else x)) | |
# effectiveness_overall=np.where(effectiveness_overall[effectiveness_overall['ResponseMetricName']=="Adjusted Account Approval BAU"],"Adjusted Account Approval BAU",effectiveness_overall['ResponseMetricName']) | |
effectiveness_overall.replace({'ResponseMetricName':{'BAU approved clients - Appsflyer':'Approved clients - Appsflyer', | |
'Gamified approved clients - Appsflyer':'Approved clients - Appsflyer'}},inplace=True) | |
# st.write(effectiveness_overall.sort_values(by=['ResponseMetricValue'],ascending=False)) | |
condition = effectiveness_overall['ResponseMetricName'] == "Adjusted Account Approval BAU" | |
condition1= effectiveness_overall['ResponseMetricName'] == "Approved clients - Appsflyer" | |
effectiveness_overall['ResponseMetric'] = np.where(condition, "Adjusted Account Approval BAU", effectiveness_overall['ResponseMetric']) | |
effectiveness_overall['ResponseMetricName'] = np.where(condition1, "Approved clients - Appsflyer (BAU, Gamified)", effectiveness_overall['ResponseMetricName']) | |
# effectiveness_overall=pd.DataFrame({'ResponseMetricName':["App Installs - Appsflyer",'Account Requests - Appsflyer', | |
# 'Total Adjusted Account Approval','Adjusted Account Approval BAU', | |
# 'Approved clients - Appsflyer','Approved clients - Appsflyer'], | |
# 'ResponseMetricValue':[683067,367020,112315,79768,36661,16834], | |
# 'Efficiency':[1.24,0.67,0.2,0.14,0.07,0.03], | |
custom_colors = { | |
'App Installs - Appsflyer': 'rgb(255, 135, 0)', # Steel Blue (Blue) | |
'Account Requests - Appsflyer': 'rgb(125, 239, 161)', # Cornflower Blue (Blue) | |
'Adjusted Account Approval': 'rgb(129, 200, 255)', # Dodger Blue (Blue) | |
'Adjusted Account Approval BAU': 'rgb(255, 207, 98)', # Light Sky Blue (Blue) | |
'Approved clients - Appsflyer': 'rgb(0, 97, 198)', # Light Blue (Blue) | |
"BAU": 'rgb(41, 176, 157)', # Steel Blue (Blue) | |
"Gamified": 'rgb(213, 218, 229)' # Silver (Gray) | |
# Add more categories and their respective shades of blue as needed | |
} | |
with columns6[0]: | |
revenue=(effectiveness_overall[effectiveness_overall['ResponseMetricName']=='Total Approved Accounts - Revenue']['ResponseMetricValue']).iloc[0] | |
revenue=round(revenue / 1_000_000, 2) | |
# st.metric('Total Revenue', f"${revenue} M") | |
# with columns6[1]: | |
# BAU=(effectiveness_overall[effectiveness_overall['ResponseMetricName']=='BAU approved clients - Revenue']['ResponseMetricValue']).iloc[0] | |
# BAU=round(BAU / 1_000_000, 2) | |
# st.metric('BAU approved clients - Revenue', f"${BAU} M") | |
# with columns6[2]: | |
# Gam=(effectiveness_overall[effectiveness_overall['ResponseMetricName']=='Gamified approved clients - Revenue']['ResponseMetricValue']).iloc[0] | |
# Gam=round(Gam / 1_000_000, 2) | |
# st.metric('Gamified approved clients - Revenue', f"${Gam} M") | |
# st.write(effectiveness_overall) | |
data = {'Revenue': ['BAU approved clients - Revenue', 'Gamified approved clients- Revenue'], | |
'ResponseMetricValue': [70200000, 1770000], | |
'Efficiency':[127.54,3.21]} | |
df = pd.DataFrame(data) | |
columns9=st.columns([0.60,0.40]) | |
with columns9[0]: | |
figd = px.pie(df, | |
names='Revenue', | |
values='ResponseMetricValue', | |
hole=0.3, # set the size of the hole in the donut | |
title='Effectiveness') | |
figd.update_layout( | |
margin=dict(l=0, r=0, b=0, t=0),width=100, height=180,legend=dict( | |
orientation='v', # set orientation to horizontal | |
x=0, # set x to 0 to move to the left | |
y=0.8 # adjust y as needed | |
) | |
) | |
st.plotly_chart(figd, use_container_width=True) | |
with columns9[1]: | |
figd1 = px.pie(df, | |
names='Revenue', | |
values='Efficiency', | |
hole=0.3, # set the size of the hole in the donut | |
title='Efficiency') | |
figd1.update_layout( | |
margin=dict(l=0, r=0, b=0, t=0),width=100,height=180,showlegend=False | |
) | |
st.plotly_chart(figd1, use_container_width=True) | |
effectiveness_overall['Response Metric Name']=effectiveness_overall['ResponseMetricName'] | |
columns4= st.columns([0.55,0.45]) | |
with columns4[0]: | |
fig=px.funnel(effectiveness_overall[~(effectiveness_overall['ResponseMetricName'].isin(['Total Approved Accounts - Revenue', | |
'BAU approved clients - Revenue', | |
'Gamified approved clients - Revenue', | |
"Total Approved Accounts - Appsflyer"]))], | |
x='ResponseMetricValue', y='Response Metric Name',color='ResponseMetric', | |
color_discrete_map=custom_colors,title='Effectiveness', | |
labels=None) | |
custom_y_labels=['App Installs - Appsflyer','Account Requests - Appsflyer','Adjusted Account Approval','Adjusted Account Approval BAU', | |
"Approved clients - Appsflyer (BAU, Gamified)" | |
] | |
fig.update_layout(showlegend=False, | |
yaxis=dict( | |
tickmode='array', | |
ticktext=custom_y_labels, | |
) | |
) | |
fig.update_traces(textinfo='value', textposition='inside', texttemplate='%{x:.2s} ', hoverinfo='y+x+percent initial') | |
last_trace_index = len(fig.data) - 1 | |
fig.update_traces(marker=dict(line=dict(color='black', width=2)), selector=dict(marker=dict(color='blue'))) | |
st.plotly_chart(fig,use_container_width=True) | |
with columns4[1]: | |
# Your existing code for creating the bar chart | |
fig1 = px.bar((effectiveness_overall[~(effectiveness_overall['ResponseMetricName'].isin(['Total Approved Accounts - Revenue', | |
'BAU approved clients - Revenue', | |
'Gamified approved clients - Revenue', | |
"Total Approved Accounts - Appsflyer"]))]).sort_values(by='ResponseMetricValue'), | |
x='Efficiency', y='Response Metric Name', | |
color_discrete_map=custom_colors, color='ResponseMetric', | |
labels=None,text_auto=True,title='Efficiency' | |
) | |
# Update layout and traces | |
fig1.update_traces(customdata=effectiveness_overall['Efficiency'], | |
textposition='auto') | |
fig1.update_layout(showlegend=False) | |
fig1.update_yaxes(title='',showticklabels=False) | |
fig1.update_xaxes(title='',showticklabels=False) | |
fig1.update_xaxes(tickfont=dict(size=20)) | |
fig1.update_yaxes(tickfont=dict(size=20)) | |
st.plotly_chart(fig1, use_container_width=True) | |
effectiveness_overall_revenue=pd.DataFrame({'ResponseMetricName':['Approved Clients','Approved Clients'], | |
'ResponseMetricValue':[70201070,1768900], | |
'Efficiency':[127.54,3.21], | |
'ResponseMetric':['BAU','Gamified'] | |
}) | |
# from plotly.subplots import make_subplots | |
# fig = make_subplots(rows=1, cols=2, | |
# subplot_titles=["Effectiveness", "Efficiency"]) | |
# # Add first plot as subplot | |
# fig.add_trace(go.Funnel( | |
# x = fig.data[0].x, | |
# y = fig.data[0].y, | |
# textinfo = 'value+percent initial', | |
# hoverinfo = 'x+y+percent initial' | |
# ), row=1, col=1) | |
# # Update layout for first subplot | |
# fig.update_xaxes(title_text="Response Metric Value", row=1, col=1) | |
# fig.update_yaxes(ticktext = custom_y_labels, row=1, col=1) | |
# # Add second plot as subplot | |
# fig.add_trace(go.Bar( | |
# x = fig1.data[0].x, | |
# y = fig1.data[0].y, | |
# customdata = fig1.data[0].customdata, | |
# textposition = 'auto' | |
# ), row=1, col=2) | |
# # Update layout for second subplot | |
# fig.update_xaxes(title_text="Efficiency", showticklabels=False, row=1, col=2) | |
# fig.update_yaxes(title='', showticklabels=False, row=1, col=2) | |
# fig.update_layout(height=600, width=800, title_text="Key Metrics") | |
# st.plotly_chart(fig) | |
st.header('Return Forecast by Media Channel') | |
with st.expander("Return Forecast by Media Channel"): | |
metric_data=[val for val in list(st.session_state['raw_data']['ResponseMetricName'].unique()) if val!=np.NaN] | |
# st.write(metric_data) | |
metric=st.selectbox('Select Metric',metric_data,index=1) | |
selected_metric=st.session_state['raw_data'][st.session_state['raw_data']['ResponseMetricName']==metric] | |
# st.dataframe(selected_metric.head(2)) | |
selected_metric=st.session_state['raw_data'][st.session_state['raw_data']['ResponseMetricName']==metric] | |
effectiveness=selected_metric.groupby(by=['MediaChannelName'])['ResponseMetricValue'].sum() | |
effectiveness_df=pd.DataFrame({'Channel':effectiveness.index,"ResponseMetricValue":effectiveness.values}) | |
summary_df_sorted=summary_df_sorted.merge(effectiveness_df,left_on="Channel_name",right_on='Channel') | |
# | |
summary_df_sorted['Efficiency'] = summary_df_sorted['ResponseMetricValue'] / summary_df_sorted['Optimized_spend'] | |
summary_df_sorted=summary_df_sorted.sort_values(by='Optimized_spend',ascending=True) | |
#st.dataframe(summary_df_sorted) | |
channel_colors = px.colors.qualitative.Plotly | |
fig = make_subplots(rows=1, cols=3, subplot_titles=('Optimized Spends', 'Effectiveness', 'Efficiency'), horizontal_spacing=0.05) | |
for i, channel in enumerate(summary_df_sorted['Channel_name'].unique()): | |
channel_df = summary_df_sorted[summary_df_sorted['Channel_name'] == channel] | |
channel_color = channel_colors[i % len(channel_colors)] | |
fig.add_trace(go.Bar(x=channel_df['Optimized_spend'], | |
y=channel_df['Channel_name'], | |
text=channel_df['Optimized_spend'].apply(format_number), | |
marker_color=channel_color, | |
orientation='h'), row=1, col=1) | |
fig.add_trace(go.Bar(x=channel_df['ResponseMetricValue'], | |
y=channel_df['Channel_name'], | |
text=channel_df['ResponseMetricValue'].apply(format_number), | |
marker_color=channel_color, | |
orientation='h', showlegend=False), row=1, col=2) | |
fig.add_trace(go.Bar(x=channel_df['Efficiency'], | |
y=channel_df['Channel_name'], | |
text=channel_df['Efficiency'].apply(format_number), | |
marker_color=channel_color, | |
orientation='h', showlegend=False), row=1, col=3) | |
fig.update_layout( | |
height=600, | |
width=900, | |
title='Media Channel Performance', | |
showlegend=False | |
) | |
fig.update_yaxes(showticklabels=False ,row=1, col=2 ) | |
fig.update_yaxes(showticklabels=False, row=1, col=3) | |
fig.update_xaxes(showticklabels=False, row=1, col=1) | |
fig.update_xaxes(showticklabels=False, row=1, col=2) | |
fig.update_xaxes(showticklabels=False, row=1, col=3) | |
st.plotly_chart(fig, use_container_width=True) | |
# columns= st.columns(3) | |
# with columns[0]: | |
# fig=summary_plot(summary_df_sorted, x='Optimized_spend', y='Channel_name', title='', text_column='Optimized_spend',color='Channel_name') | |
# st.plotly_chart(fig,use_container_width=True) | |
# with columns[1]: | |
# # effectiveness=(selected_metric.groupby(by=['MediaChannelName'])['ResponseMetricValue'].sum()).values | |
# # effectiveness_df=pd.DataFrame({'Channel':st.session_state['raw_data']['MediaChannelName'].unique(),"ResponseMetricValue":effectiveness}) | |
# # # effectiveness.reset_index(inplace=True) | |
# # # st.dataframe(effectiveness.head()) | |
# fig=summary_plot(summary_df_sorted, x='ResponseMetricValue', y='Channel_name', title='Effectiveness', text_column='ResponseMetricValue',color='Channel_name') | |
# st.plotly_chart(fig,use_container_width=True) | |
# with columns[2]: | |
# fig=summary_plot(summary_df_sorted, x='Efficiency', y='Channel_name', title='Efficiency', text_column='Efficiency',color='Channel_name',format_as_decimal=True) | |
# st.plotly_chart(fig,use_container_width=True) | |
# Create figure with subplots | |
# fig = make_subplots(rows=1, cols=2) | |
# # Add funnel plot to subplot 1 | |
# fig.add_trace( | |
# go.Funnel( | |
# x=effectiveness_overall[~(effectiveness_overall['ResponseMetricName'].isin(['Total Approved Accounts - Revenue', 'BAU approved clients - Revenue', 'Gamified approved clients - Revenue', "Total Approved Accounts - Appsflyer"]))]['ResponseMetricValue'], | |
# y=effectiveness_overall[~(effectiveness_overall['ResponseMetricName'].isin(['Total Approved Accounts - Revenue', 'BAU approved clients - Revenue', 'Gamified approved clients - Revenue', "Total Approved Accounts - Appsflyer"]))]['ResponseMetricName'], | |
# textposition="inside", | |
# texttemplate="%{x:.2s}", | |
# customdata=effectiveness_overall['Efficiency'], | |
# hovertemplate="%{customdata:.2f}<extra></extra>" | |
# ), | |
# row=1, col=1 | |
# ) | |
# # Add bar plot to subplot 2 | |
# fig.add_trace( | |
# go.Bar( | |
# x=effectiveness_overall.sort_values(by='ResponseMetricValue')['Efficiency'], | |
# y=effectiveness_overall.sort_values(by='ResponseMetricValue')['ResponseMetricName'], | |
# marker_color=effectiveness_overall['ResponseMetric'], | |
# customdata=effectiveness_overall['Efficiency'], | |
# hovertemplate="%{customdata:.2f}<extra></extra>", | |
# textposition="outside" | |
# ), | |
# row=1, col=2 | |
# ) | |
# # Update layout | |
# fig.update_layout(title_text="Effectiveness") | |
# fig.update_yaxes(title_text="", row=1, col=1) | |
# fig.update_yaxes(title_text="", showticklabels=False, row=1, col=2) | |
# fig.update_xaxes(title_text="Efficiency", showticklabels=False, row=1, col=2) | |
# # Show figure | |
# st.plotly_chart(fig) |