MMA_DFS_ROO / src /streamlit_app.py
James McCool
ping
d7b175f
raw
history blame
30.3 kB
import streamlit as st
import numpy as np
import pandas as pd
import pymongo
import os
import unicodedata
from database import db
st.set_page_config(layout="wide")
player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '100+%': '{:.2%}', '10x%': '{:.2%}', '11x%': '{:.2%}', '12x%': '{:.2%}'}
dk_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6', 'salary', 'proj', 'Own']
fd_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6', 'salary', 'proj', 'Own']
### I should probably not have this be messy in terms of site declarations but eh
st.markdown("""
<style>
/* Tab styling */
.stElementContainer [data-baseweb="button-group"] {
gap: 8px;
padding: 4px;
}
.stElementContainer [kind="segmented_control"] {
height: 45px;
white-space: pre-wrap;
background-color: #DAA520;
color: white;
border-radius: 10px;
gap: 1px;
padding: 10px 20px;
font-weight: bold;
transition: all 0.3s ease;
}
.stElementContainer [kind="segmented_controlActive"] {
height: 50px;
background-color: #DAA520;
border: 3px solid #FFD700;
color: white;
}
.stElementContainer [kind="segmented_control"]:hover {
background-color: #FFD700;
cursor: pointer;
}
div[data-baseweb="select"] > div {
background-color: #DAA520;
color: white;
}
</style>""", unsafe_allow_html=True)
@st.cache_resource(ttl = 60)
def init_baselines():
collection = db["Player_Level_ROO"]
cursor = collection.find()
player_frame = pd.DataFrame(cursor)
roo_data = player_frame.drop(columns=['_id'])
roo_data['Salary'] = roo_data['Salary'].astype(int)
return roo_data
@st.cache_data(ttl = 60)
def init_DK_lineups(type):
if type == 'Regular':
collection = db['DK_MMA_name_map']
elif type == 'Showdown':
collection = db['DK_SD_MMA_name_map']
cursor = collection.find()
raw_data = pd.DataFrame(list(cursor))
names_dict = dict(zip(raw_data['key'], raw_data['value']))
if type == 'Regular':
collection = db["DK_MMA_seed_frame_Main Slate"]
elif type == 'Showdown':
collection = db["DK_SD_MMA_seed_frame_Main Slate"]
cursor = collection.find().limit(10000)
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display[['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6', 'salary', 'proj', 'Own']]
dict_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
for col in dict_columns:
raw_display[col] = raw_display[col].map(names_dict)
DK_seed = raw_display.to_numpy()
return DK_seed
@st.cache_data(ttl = 60)
def init_FD_lineups(type):
if type == 'Regular':
collection = db['FD_MMA_name_map']
elif type == 'Showdown':
collection = db['FD_SD_MMA_name_map']
cursor = collection.find()
raw_data = pd.DataFrame(list(cursor))
names_dict = dict(zip(raw_data['key'], raw_data['value']))
if type == 'Regular':
collection = db["FD_MMA_seed_frame_Main Slate"]
elif type == 'Showdown':
collection = db["FD_SD_MMA_seed_frame_Main Slate"]
cursor = collection.find().limit(10000)
raw_display = pd.DataFrame(list(cursor))
raw_display = raw_display[['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6', 'salary', 'proj', 'Own']]
dict_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
for col in dict_columns:
raw_display[col] = raw_display[col].map(names_dict)
FD_seed = raw_display.to_numpy()
return FD_seed
def normalize_special_characters(text):
"""Convert accented characters to their ASCII equivalents"""
if pd.isna(text):
return text
# Normalize unicode characters to their closest ASCII equivalents
normalized = unicodedata.normalize('NFKD', str(text))
# Remove diacritics (accents, umlauts, etc.)
ascii_text = ''.join(c for c in normalized if not unicodedata.combining(c))
return ascii_text
def convert_df_to_csv(df):
df_clean = df.copy()
for col in df_clean.columns:
if df_clean[col].dtype == 'object':
df_clean[col] = df_clean[col].apply(normalize_special_characters)
return df_clean.to_csv(index=False).encode('utf-8')
@st.cache_data
def convert_df(array):
array = pd.DataFrame(array, columns=column_names)
# Normalize special characters in the dataframe before export
for col in array.columns:
if array[col].dtype == 'object':
array[col] = array[col].apply(normalize_special_characters)
return array.to_csv(index=False).encode('utf-8')
@st.cache_data
def convert_pm_df(array):
array = pd.DataFrame(array)
# Normalize special characters in the dataframe before export
for col in array.columns:
if array[col].dtype == 'object':
array[col] = array[col].apply(normalize_special_characters)
return array.to_csv(index=False).encode('utf-8')
roo_data = init_baselines()
dk_id_dict = dict(zip(roo_data['Player'], roo_data['player_id']))
dk_id_dict_sd = {}
fd_id_dict = dict(zip(roo_data['Player'], roo_data['player_id']))
fd_id_dict_sd = {}
hold_display = roo_data
app_load_reset_column, app_view_site_column = st.columns([1, 9])
with app_load_reset_column:
if st.button("Load/Reset Data", key='reset_data_button'):
st.cache_data.clear()
roo_data = init_baselines()
dk_id_dict = dict(zip(roo_data['Player'], roo_data['player_id']))
dk_id_dict_sd = {}
fd_id_dict = dict(zip(roo_data['Player'], roo_data['player_id']))
fd_id_dict_sd = {}
dk_lineups = init_DK_lineups('Regular')
fd_lineups = init_FD_lineups('Regular')
hold_display = roo_data
for key in st.session_state.keys():
del st.session_state[key]
with app_view_site_column:
with st.container():
app_view_column, app_site_column = st.columns([3, 3])
with app_view_column:
view_var = st.selectbox("Select view", ["Simple", "Advanced"], key='view_selectbox')
with app_site_column:
site_var = st.selectbox("What site do you want to view?", ('Draftkings'), key='site_selectbox')
selected_tab = st.segmented_control(
"Select Tab",
options=["Player ROO", "Optimals"],
selection_mode='single',
default='Player ROO',
width='stretch',
label_visibility='collapsed',
key='tab_selector'
)
if selected_tab == "Player ROO":
with st.expander("Info and Filters"):
if st.button("Reset Data", key='reset1'):
st.cache_data.clear()
roo_data = init_baselines()
dk_id_dict = dict(zip(roo_data['Player'], roo_data['player_id']))
dk_id_dict_sd = {}
fd_id_dict = dict(zip(roo_data['Player'], roo_data['player_id']))
fd_id_dict_sd = {}
dk_lineups = init_DK_lineups('Regular')
fd_lineups = init_FD_lineups('Regular')
hold_display = roo_data
for key in st.session_state.keys():
del st.session_state[key]
type_var = st.radio("Select a Type", ["Full Slate"])
if type_var == "Full Slate":
display = hold_display[hold_display['Site'] == site_var]
display = display.drop_duplicates(subset=['Player'])
elif type_var == "Showdown":
display = pd.DataFrame()
display = display.drop_duplicates(subset=['Player'])
export_data = display.copy()
export_data_pm = display[['Player', 'Salary', 'Median', 'Own']]
export_data_pm['Position'] = 'FLEX'
export_data_pm['Team'] = 'MMA'
export_data_pm['captain ownership'] = ''
export_data_pm = export_data_pm.rename(columns={'Own': 'ownership', 'Median': 'median', 'Player': 'player_names', 'Position': 'position', 'Team': 'team', 'Salary': 'salary'})
reg_dl_col, pm_dl_col, blank_col = st.columns([2, 2, 6])
with reg_dl_col:
st.download_button(
label="Export ROO (Regular)",
data=convert_df_to_csv(export_data),
file_name='MMA_ROO_export.csv',
mime='text/csv',
)
with pm_dl_col:
st.download_button(
label="Export ROO (Portfolio Manager)",
data=convert_df_to_csv(export_data_pm),
file_name='MMA_ROO_export.csv',
mime='text/csv',
)
with st.container():
if view_var == "Simple":
if type_var == "Full Slate":
display = display[['Player', 'Salary', 'Median', '10x%', 'Own']]
display = display.set_index('Player')
elif type_var == "Showdown":
display = display[['Player', 'Salary', 'Median', '5x%', 'Own']]
display = display.set_index('Player')
st.dataframe(display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True)
elif view_var == "Advanced":
display = display
display = display.set_index('Player')
st.dataframe(display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), height=750, use_container_width = True)
if selected_tab == "Optimals":
with st.expander("Info and Filters"):
if st.button("Load/Reset Data", key='reset2'):
st.cache_data.clear()
roo_data = init_baselines()
dk_id_dict = dict(zip(roo_data['Player'], roo_data['player_id']))
dk_id_dict_sd = {}
fd_id_dict = dict(zip(roo_data['Player'], roo_data['player_id']))
fd_id_dict_sd = {}
hold_display = roo_data
dk_lineups = init_DK_lineups('Regular')
fd_lineups = init_FD_lineups('Regular')
for key in st.session_state.keys():
del st.session_state[key]
col1, col2, col3, col4 = st.columns(4)
with col1:
slate_var1 = st.radio("Which data are you loading?", ('Regular'))
if slate_var1 == 'Regular':
if site_var == 'Draftkings':
dk_lineups = init_DK_lineups('Regular')
id_dict = dk_id_dict.copy()
elif site_var == 'Fanduel':
fd_lineups = init_FD_lineups('Regular')
id_dict = fd_id_dict.copy()
elif slate_var1 == 'Showdown':
if site_var == 'Draftkings':
dk_lineups = init_DK_lineups('Showdown')
id_dict_sd = dk_id_dict_sd.copy()
elif site_var == 'Fanduel':
fd_lineups = init_FD_lineups('Showdown')
id_dict_sd = fd_id_dict_sd.copy()
if slate_var1 == 'Regular':
raw_baselines = roo_data
elif slate_var1 == 'Showdown':
raw_baselines = pd.DataFrame()
if site_var == 'Draftkings':
if slate_var1 == 'Regular':
ROO_slice = raw_baselines
player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
elif slate_var1 == 'Showdown':
player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
# Get the minimum and maximum ownership values from dk_lineups
min_own = np.min(dk_lineups[:,8])
max_own = np.max(dk_lineups[:,8])
column_names = dk_columns
elif site_var == 'Fanduel':
raw_baselines = hold_display
if slate_var1 == 'Regular':
ROO_slice = raw_baselines
player_salaries = dict(zip(ROO_slice['Player'], ROO_slice['Salary']))
elif slate_var1 == 'Showdown':
player_salaries = dict(zip(raw_baselines['Player'], raw_baselines['Salary']))
min_own = np.min(fd_lineups[:,8])
max_own = np.max(fd_lineups[:,8])
column_names = fd_columns
with col2:
lineup_num_var = st.number_input("How many lineups do you want to display?", min_value=1, max_value=1000, value=150, step=1)
with col3:
player_var1 = st.radio("Do you want a frame with specific Players?", ('Full Slate', 'Specific Players'), key='player_var1')
if player_var1 == 'Specific Players':
player_var2 = st.multiselect('Which players do you want?', options = raw_baselines['Player'].unique())
elif player_var1 == 'Full Slate':
player_var2 = raw_baselines.Player.values.tolist()
with col4:
if site_var == 'Draftkings':
salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 50000, value = 49000, step = 100, key = 'salary_min_var')
salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 50000, value = 50000, step = 100, key = 'salary_max_var')
elif site_var == 'Fanduel':
salary_min_var = st.number_input("Minimum salary used", min_value = 0, max_value = 60000, value = 59000, step = 100, key = 'salary_min_var')
salary_max_var = st.number_input("Maximum salary used", min_value = 0, max_value = 60000, value = 60000, step = 100, key = 'salary_max_var')
reg_dl_col, filtered_dl_col, blank_dl_col = st.columns([2, 2, 6])
with reg_dl_col:
if st.button("Prepare full data export", key='data_export'):
name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
if site_var == 'Draftkings':
if slate_var1 == 'Regular':
map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
elif slate_var1 == 'Showdown':
map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
elif site_var == 'Fanduel':
if slate_var1 == 'Regular':
map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
elif slate_var1 == 'Showdown':
map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
for col_idx in map_columns:
if slate_var1 == 'Regular':
data_export[col_idx] = data_export[col_idx].map(id_dict)
elif slate_var1 == 'Showdown':
data_export[col_idx] = data_export[col_idx].map(id_dict_sd)
pm_name_export = name_export.drop(columns=['salary', 'proj', 'Own'], axis=1)
pm_data_export = data_export.drop(columns=['salary', 'proj', 'Own'], axis=1)
reg_opt_col, pm_opt_col = st.columns(2)
with reg_opt_col:
st.download_button(
label="Export optimals set (IDs)",
data=convert_df(data_export),
file_name='MMA_optimals_export.csv',
mime='text/csv',
)
st.download_button(
label="Export optimals set (Names)",
data=convert_df(name_export),
file_name='MMA_optimals_export.csv',
mime='text/csv',
)
with pm_opt_col:
st.download_button(
label="Portfolio Manager Export (IDs)",
data=convert_pm_df(pm_data_export),
file_name='MMA_optimals_export.csv',
mime='text/csv',
)
st.download_button(
label="Portfolio Manager Export (Names)",
data=convert_pm_df(pm_name_export),
file_name='MMA_optimals_export.csv',
mime='text/csv',
)
with filtered_dl_col:
if st.button("Prepare full data export (Filtered)", key='data_export_filtered'):
name_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
data_export = pd.DataFrame(st.session_state.working_seed.copy(), columns=column_names)
if site_var == 'Draftkings':
if slate_var1 == 'Regular':
map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
elif slate_var1 == 'Showdown':
map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
elif site_var == 'Fanduel':
if slate_var1 == 'Regular':
map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
elif slate_var1 == 'Showdown':
map_columns = ['FLEX1', 'FLEX2', 'FLEX3', 'FLEX4', 'FLEX5', 'FLEX6']
for col_idx in map_columns:
if slate_var1 == 'Regular':
data_export[col_idx] = data_export[col_idx].map(id_dict)
elif slate_var1 == 'Showdown':
data_export[col_idx] = data_export[col_idx].map(id_dict_sd)
data_export = data_export[data_export['salary'] >= salary_min_var]
data_export = data_export[data_export['salary'] <= salary_max_var]
name_export = name_export[name_export['salary'] >= salary_min_var]
name_export = name_export[name_export['salary'] <= salary_max_var]
pm_name_export = name_export.drop(columns=['salary', 'proj', 'Own'], axis=1)
pm_data_export = data_export.drop(columns=['salary', 'proj', 'Own'], axis=1)
reg_opt_col, pm_opt_col = st.columns(2)
with reg_opt_col:
st.download_button(
label="Export optimals set (IDs)",
data=convert_df(data_export),
file_name='MMA_optimals_export.csv',
mime='text/csv',
)
st.download_button(
label="Export optimals set (Names)",
data=convert_df(name_export),
file_name='MMA_optimals_export.csv',
mime='text/csv',
)
with pm_opt_col:
st.download_button(
label="Portfolio Manager Export (IDs)",
data=convert_pm_df(pm_data_export),
file_name='MMA_optimals_export.csv',
mime='text/csv',
)
st.download_button(
label="Portfolio Manager Export (Names)",
data=convert_pm_df(pm_name_export),
file_name='MMA_optimals_export.csv',
mime='text/csv',
)
if site_var == 'Draftkings':
if 'working_seed' in st.session_state:
st.session_state.working_seed = st.session_state.working_seed
if player_var1 == 'Specific Players':
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
elif player_var1 == 'Full Slate':
st.session_state.working_seed = dk_lineups.copy()
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
elif 'working_seed' not in st.session_state:
st.session_state.working_seed = dk_lineups.copy()
st.session_state.working_seed = st.session_state.working_seed
if player_var1 == 'Specific Players':
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
elif player_var1 == 'Full Slate':
st.session_state.working_seed = dk_lineups.copy()
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
elif site_var == 'Fanduel':
if 'working_seed' in st.session_state:
st.session_state.working_seed = st.session_state.working_seed
if player_var1 == 'Specific Players':
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
elif player_var1 == 'Full Slate':
st.session_state.working_seed = fd_lineups.copy()
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
elif 'working_seed' not in st.session_state:
st.session_state.working_seed = fd_lineups.copy()
st.session_state.working_seed = st.session_state.working_seed
if player_var1 == 'Specific Players':
st.session_state.working_seed = st.session_state.working_seed[np.equal.outer(st.session_state.working_seed, player_var2).any(axis=1).all(axis=1)]
elif player_var1 == 'Full Slate':
st.session_state.working_seed = fd_lineups.copy()
st.session_state.data_export_display = pd.DataFrame(st.session_state.working_seed[0:lineup_num_var], columns=column_names)
export_file = st.session_state.data_export_display.copy()
# if site_var1 == 'Draftkings':
# for col_idx in range(6):
# export_file.iloc[:, col_idx] = export_file.iloc[:, col_idx].map(id_dict)
# elif site_var1 == 'Fanduel':
# for col_idx in range(6):
# export_file.iloc[:, col_idx] = export_file.iloc[:, col_idx].map(id_dict)
with st.container():
if st.button("Reset Optimals", key='reset3'):
for key in st.session_state.keys():
del st.session_state[key]
if site_var == 'Draftkings':
st.session_state.working_seed = dk_lineups.copy()
elif site_var == 'Fanduel':
st.session_state.working_seed = fd_lineups.copy()
st.session_state.data_export_display = st.session_state.data_export_display[st.session_state.data_export_display['salary'].between(salary_min_var, salary_max_var)]
if 'data_export_display' in st.session_state:
st.dataframe(st.session_state.data_export_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), height=500, use_container_width = True)
st.download_button(
label="Export display optimals",
data=convert_df(export_file),
file_name='MMA_display_optimals.csv',
mime='text/csv',
)
with st.container():
if 'working_seed' in st.session_state:
# Create a new dataframe with summary statistics
if site_var == 'Draftkings':
summary_df = pd.DataFrame({
'Metric': ['Min', 'Average', 'Max', 'STDdev'],
'Salary': [
np.min(st.session_state.working_seed[:,6]),
np.mean(st.session_state.working_seed[:,6]),
np.max(st.session_state.working_seed[:,6]),
np.std(st.session_state.working_seed[:,6])
],
'Proj': [
np.min(st.session_state.working_seed[:,7]),
np.mean(st.session_state.working_seed[:,7]),
np.max(st.session_state.working_seed[:,7]),
np.std(st.session_state.working_seed[:,7])
],
'Own': [
np.min(st.session_state.working_seed[:,8]),
np.mean(st.session_state.working_seed[:,8]),
np.max(st.session_state.working_seed[:,8]),
np.std(st.session_state.working_seed[:,8])
]
})
elif site_var == 'Fanduel':
summary_df = pd.DataFrame({
'Metric': ['Min', 'Average', 'Max', 'STDdev'],
'Salary': [
np.min(st.session_state.working_seed[:,6]),
np.mean(st.session_state.working_seed[:,6]),
np.max(st.session_state.working_seed[:,6]),
np.std(st.session_state.working_seed[:,6])
],
'Proj': [
np.min(st.session_state.working_seed[:,7]),
np.mean(st.session_state.working_seed[:,7]),
np.max(st.session_state.working_seed[:,7]),
np.std(st.session_state.working_seed[:,7])
],
'Own': [
np.min(st.session_state.working_seed[:,8]),
np.mean(st.session_state.working_seed[:,8]),
np.max(st.session_state.working_seed[:,8]),
np.std(st.session_state.working_seed[:,8])
]
})
# Set the index of the summary dataframe as the "Metric" column
summary_df = summary_df.set_index('Metric')
# Display the summary dataframe
st.subheader("Optimal Statistics")
st.dataframe(summary_df.style.format({
'Salary': '{:.2f}',
'Proj': '{:.2f}',
'Own': '{:.2f}'
}).background_gradient(cmap='RdYlGn', axis=0, subset=['Salary', 'Proj', 'Own']), use_container_width=True)
with st.container():
tab1, tab2 = st.tabs(["Display Frequency", "Seed Frame Frequency"])
with tab1:
if 'data_export_display' in st.session_state:
if site_var == 'Draftkings':
player_columns = st.session_state.data_export_display.iloc[:, :6]
elif site_var == 'Fanduel':
player_columns = st.session_state.data_export_display.iloc[:, :6]
# Flatten the DataFrame and count unique values
value_counts = player_columns.values.flatten().tolist()
value_counts = pd.Series(value_counts).value_counts()
percentages = (value_counts / lineup_num_var * 100).round(2)
# Create a DataFrame with the results
summary_df = pd.DataFrame({
'Player': value_counts.index,
'Frequency': value_counts.values,
'Percentage': percentages.values
})
# Sort by frequency in descending order
summary_df['Salary'] = summary_df['Player'].map(player_salaries)
summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
summary_df = summary_df.sort_values('Frequency', ascending=False)
summary_df = summary_df.set_index('Player')
# Display the table
st.write("Player Frequency Table:")
st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True)
st.download_button(
label="Export player frequency",
data=convert_df_to_csv(summary_df),
file_name='MMA_player_frequency.csv',
mime='text/csv',
)
with tab2:
if 'working_seed' in st.session_state:
if site_var == 'Draftkings':
player_columns = st.session_state.working_seed[:, :6]
elif site_var == 'Fanduel':
player_columns = st.session_state.working_seed[:, :6]
# Flatten the DataFrame and count unique values
value_counts = player_columns.flatten().tolist()
value_counts = pd.Series(value_counts).value_counts()
percentages = (value_counts / len(st.session_state.working_seed) * 100).round(2)
# Create a DataFrame with the results
summary_df = pd.DataFrame({
'Player': value_counts.index,
'Frequency': value_counts.values,
'Percentage': percentages.values
})
# Sort by frequency in descending order
summary_df['Salary'] = summary_df['Player'].map(player_salaries)
summary_df = summary_df[['Player', 'Salary', 'Frequency', 'Percentage']]
summary_df = summary_df.sort_values('Frequency', ascending=False)
summary_df = summary_df.set_index('Player')
# Display the table
st.write("Seed Frame Frequency Table:")
st.dataframe(summary_df.style.format({'Percentage': '{:.2f}%'}), height=500, use_container_width=True)
st.download_button(
label="Export seed frame frequency",
data=convert_df_to_csv(summary_df),
file_name='MMA_seed_frame_frequency.csv',
mime='text/csv',
)