import pandas as pd import numpy as np import requests import math import streamlit as st st.set_page_config(layout="wide") Dwain_proj = 'https://sheetdb.io/api/v1/svino07zkd6j6?sheet=2025_NFL_Proj_Dist' dwain_ranks = 'https://sheetdb.io/api/v1/ax8b1ms11bbzt?sheet=Dwain_Season' # Default configuration dictionaries type_flex_percentiles = { 'Half PPR': { 'RB': .40, 'WR': .55, 'TE': .05, }, 'PPR': { 'RB': .40, 'WR': .55, 'TE': .05, }, 'Standard': { 'RB': .40, 'WR': .55, 'TE': .05, }, 'Superflex': { 'QB': .95, 'RB': .02, 'WR': .03, 'TE': .00, }, 'TE Premium': { 'RB': .35, 'WR': .50, 'TE': .15, } } pos_vorp_limiters = { 'PPR': { 'QB': .27, 'RB': .440, 'WR': .460, 'TE': .27, }, 'Standard': { 'QB': .27, 'RB': .50, 'WR': .50, 'TE': .27, }, 'Superflex': { 'QB': .99, 'RB': .27, 'WR': .27, 'TE': .27, }, 'TE Premium': { 'QB': .27, 'RB': .440, 'WR': .460, 'TE': .27, }, 'Half PPR': { 'QB': .27, 'RB': .440, 'WR': .460, 'TE': .27, }, } flex_multipliers = { 'Half PPR': { 'QB': 1, 'RB': 1, 'WR': 1, 'TE': 1, }, 'PPR': { 'QB': 1, 'RB': 1, 'WR': 1, 'TE': 1, }, 'Standard': { 'QB': 1, 'RB': 1, 'WR': 1, 'TE': 1, }, 'Superflex': { 'QB': 4, 'RB': 1, 'WR': 1, 'TE': 1, }, 'TE Premium': { 'QB': 1, 'RB': 1, 'WR': 1, 'TE': 2, }, } base_settings = { 'TEAMS': 12, 'QB': 1, 'RB': 2, 'WR': 3, 'TE': 1, 'FLEX': 1, 'BENCH': 6, 'TYPE': 'Half PPR' } league_settings = { 'TEAMS': 12, 'QB': 1, 'RB': 2, 'WR': 3, 'TE': 1, 'FLEX': 1, 'BENCH': 6, 'TYPE': 'PPR' } def create_user_config_interface(): """Create Streamlit interface for user configuration""" st.sidebar.header("League Configuration") # League Type Selection league_type = st.sidebar.selectbox( "League Type", ['Half PPR', 'PPR', 'Standard', 'Superflex', 'TE Premium'], index=0 ) # League Settings st.sidebar.subheader("League Settings") teams = st.sidebar.number_input("Number of Teams", min_value=8, max_value=16, value=12) qb_starters = st.sidebar.number_input("QB Starters", min_value=1, max_value=2, value=1) rb_starters = st.sidebar.number_input("RB Starters", min_value=1, max_value=3, value=2) wr_starters = st.sidebar.number_input("WR Starters", min_value=1, max_value=4, value=3) te_starters = st.sidebar.number_input("TE Starters", min_value=1, max_value=2, value=1) flex_spots = st.sidebar.number_input("Flex Spots", min_value=0, max_value=3, value=1) bench_spots = st.sidebar.number_input("Bench Spots", min_value=0, max_value=10, value=6) # Update league settings based on user input user_league_settings = { 'TEAMS': teams, 'QB': qb_starters, 'RB': rb_starters, 'WR': wr_starters, 'TE': te_starters, 'FLEX': flex_spots, 'BENCH': bench_spots, 'TYPE': league_type } # Flex Percentiles Configuration st.sidebar.subheader("Flex Position Percentiles") if league_type == 'Superflex': qb_flex_pct = st.sidebar.slider("QB Flex %", 0.0, 1.0, 0.95, 0.01) rb_flex_pct = st.sidebar.slider("RB Flex %", 0.0, 1.0, 0.02, 0.01) wr_flex_pct = st.sidebar.slider("WR Flex %", 0.0, 1.0, 0.03, 0.01) te_flex_pct = st.sidebar.slider("TE Flex %", 0.0, 1.0, 0.00, 0.01) user_flex_percentiles = { 'QB': qb_flex_pct, 'RB': rb_flex_pct, 'WR': wr_flex_pct, 'TE': te_flex_pct, } else: # Get default values for the selected league type default_rb = type_flex_percentiles.get(league_type, {}).get('RB', 0.4) default_wr = type_flex_percentiles.get(league_type, {}).get('WR', 0.55) default_te = type_flex_percentiles.get(league_type, {}).get('TE', 0.05) rb_flex_pct = st.sidebar.slider("RB Flex %", 0.0, 1.0, default_rb, 0.01) wr_flex_pct = st.sidebar.slider("WR Flex %", 0.0, 1.0, default_wr, 0.01) te_flex_pct = st.sidebar.slider("TE Flex %", 0.0, 1.0, default_te, 0.01) user_flex_percentiles = { 'RB': rb_flex_pct, 'WR': wr_flex_pct, 'TE': te_flex_pct, } # Flex Multipliers Configuration st.sidebar.subheader("Position Multipliers") default_qb_mult = flex_multipliers.get(league_type, {}).get('QB', 2.0) default_rb_mult = flex_multipliers.get(league_type, {}).get('RB', 2.0) default_wr_mult = flex_multipliers.get(league_type, {}).get('WR', 2.0) default_te_mult = flex_multipliers.get(league_type, {}).get('TE', 2.0) qb_mult = st.sidebar.number_input("QB Multiplier", min_value=1.0, max_value=5.0, value=float(default_qb_mult), step=0.5) rb_mult = st.sidebar.number_input("RB Multiplier", min_value=1.0, max_value=5.0, value=float(default_rb_mult), step=0.5) wr_mult = st.sidebar.number_input("WR Multiplier", min_value=1.0, max_value=5.0, value=float(default_wr_mult), step=0.5) te_mult = st.sidebar.number_input("TE Multiplier", min_value=1.0, max_value=5.0, value=float(default_te_mult), step=0.5) user_flex_multipliers = { 'QB': qb_mult, 'RB': rb_mult, 'WR': wr_mult, 'TE': te_mult, } # VORP Limiters Configuration st.sidebar.subheader("VORP Rank Adjustments") default_qb_vorp = pos_vorp_limiters.get(league_type, {}).get('QB', 0.5) default_rb_vorp = pos_vorp_limiters.get(league_type, {}).get('RB', 0.75) default_wr_vorp = pos_vorp_limiters.get(league_type, {}).get('WR', 0.75) default_te_vorp = pos_vorp_limiters.get(league_type, {}).get('TE', 0.5) qb_vorp_lim = st.sidebar.slider("QB VORP Limiter", 0.0, 1.0, default_qb_vorp, 0.01) rb_vorp_lim = st.sidebar.slider("RB VORP Limiter", 0.0, 1.0, default_rb_vorp, 0.01) wr_vorp_lim = st.sidebar.slider("WR VORP Limiter", 0.0, 1.0, default_wr_vorp, 0.01) te_vorp_lim = st.sidebar.slider("TE VORP Limiter", 0.0, 1.0, default_te_vorp, 0.01) user_pos_vorp_limiters = { 'QB': qb_vorp_lim, 'RB': rb_vorp_lim, 'WR': wr_vorp_lim, 'TE': te_vorp_lim, } return user_league_settings, user_flex_percentiles, user_flex_multipliers, user_pos_vorp_limiters def load_projections_data(api: str) -> pd.DataFrame: calc_columns = ['Ru Yds', 'Ru TDs', 'Rec', 'Rec Yds', 'Rec TDs', 'P Yds', 'P TDs', 'INTs'] ppr_values = [.1, 6, 1, .1, 6, .04, 4, -1] halfPpr_values = [.1, 6, .5, .1, 6, .04, 4, -1] standard_values = [.1, 6, 0, .1, 6, .04, 4, -1] init_data = requests.get(api) proj_dataframe = pd.DataFrame(init_data.json()) for col in calc_columns: proj_dataframe[col] = proj_dataframe[col].astype(float) proj_dataframe['halfPpr'] = proj_dataframe[calc_columns].dot(halfPpr_values) proj_dataframe['ppr'] = proj_dataframe[calc_columns].dot(ppr_values) proj_dataframe['standard'] = proj_dataframe[calc_columns].dot(standard_values) fpts_df = proj_dataframe[['Name', 'SR_ID', 'Pos', 'halfPpr', 'ppr', 'standard']] return fpts_df def load_ranks_data(api: str) -> pd.DataFrame: init_data = requests.get(api) ranks_dataframe = pd.DataFrame(init_data.json()) ranks_dict = dict(zip(ranks_dataframe['SR_ID'], ranks_dataframe['Rank'])) return ranks_dict def create_position_frames(frame: pd.DataFrame, ranks: dict) -> pd.DataFrame: qb_frame = frame[frame['Pos'] == 'QB'].sort_values(by='halfPpr', ascending=False) rb_frame = frame[frame['Pos'] == 'RB'].sort_values(by='halfPpr', ascending=False) wr_frame = frame[frame['Pos'] == 'WR'].sort_values(by='halfPpr', ascending=False) te_frame = frame[frame['Pos'] == 'TE'].sort_values(by='halfPpr', ascending=False) for slice in [qb_frame, rb_frame, wr_frame, te_frame]: slice['Rank'] = slice['SR_ID'].map(ranks).replace(np.nan, 0).astype(int) slice = slice[slice['Rank'] != 0] slice = slice.sort_values(by='Rank', ascending=True) overall_frame = pd.concat([qb_frame, rb_frame, wr_frame, te_frame]).reset_index(drop=True) return overall_frame def designate_custom_position_reqs(league_settings: dict, flex_percentiles: dict, flex_multipliers: dict) -> dict: qb_base = league_settings['QB'] * league_settings['TEAMS'] rb_base = league_settings['RB'] * league_settings['TEAMS'] wr_base = league_settings['WR'] * league_settings['TEAMS'] te_base = league_settings['TE'] * league_settings['TEAMS'] if league_settings['TYPE'] == 'Superflex': qb_flex_mult = flex_multipliers['QB'] * (12 / league_settings['TEAMS']) rb_flex_mult = flex_multipliers['RB'] wr_flex_mult = flex_multipliers['WR'] te_flex_mult = flex_multipliers['TE'] qb_rv_index = min(math.ceil((qb_base) * qb_flex_mult), 48) rb_rv_index = min(math.ceil((rb_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['RB'])) * rb_flex_mult), 60) wr_rv_index = min(math.ceil((wr_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['WR'])) * wr_flex_mult), 96) te_rv_index = min(math.ceil((te_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['TE'])) * te_flex_mult), 30) elif league_settings['TYPE'] == 'TE Premium': qb_flex_mult = flex_multipliers['QB'] rb_flex_mult = flex_multipliers['RB'] wr_flex_mult = flex_multipliers['WR'] te_flex_mult = flex_multipliers['TE'] * (12 / league_settings['TEAMS']) qb_rv_index = min(math.ceil((qb_base) * qb_flex_mult), 30) rb_rv_index = min(math.ceil((rb_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['RB'])) * rb_flex_mult), 60) wr_rv_index = min(math.ceil((wr_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['WR'])) * wr_flex_mult), 96) te_rv_index = min(math.ceil((te_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['TE'])) * te_flex_mult), 48) else: qb_flex_mult = flex_multipliers['QB'] * (league_settings['TEAMS'] / 12) rb_flex_mult = flex_multipliers['RB'] wr_flex_mult = flex_multipliers['WR'] te_flex_mult = flex_multipliers['TE'] * (league_settings['TEAMS'] / 12) if league_settings['QB'] > 1: qb_rv_index = min(math.ceil((qb_base) * 4), 48) elif league_settings['QB'] == 1: qb_rv_index = min(math.ceil((qb_base) * qb_flex_mult), 30) rb_rv_index = min(math.ceil((rb_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['RB'])) * rb_flex_mult), 60) wr_rv_index = min(math.ceil((wr_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['WR'])) * wr_flex_mult), 96) te_rv_index = min(math.ceil((te_base + ((league_settings['TEAMS'] * league_settings['FLEX']) * flex_percentiles['TE'])) * te_flex_mult), 30) print(f"Need {qb_rv_index} for QB in {league_settings['TEAMS']} teams with type {league_settings['TYPE']}") print(f"Need {rb_rv_index} for RB in {league_settings['TEAMS']} teams with type {league_settings['TYPE']}") print(f"Need {wr_rv_index} for WR in {league_settings['TEAMS']} teams with type {league_settings['TYPE']}") print(f"Need {te_rv_index} for TE in {league_settings['TEAMS']} teams with type {league_settings['TYPE']}") pos_reqs = { 'QB': qb_rv_index, 'RB': rb_rv_index, 'WR': wr_rv_index, 'TE': te_rv_index, } return pos_reqs def designate_base_position_reqs() -> dict: qb_base = 1 * 12 rb_base = 2 * 12 wr_base = 3 * 12 te_base = 1 * 12 qb_rv_index = min(math.ceil(qb_base * 1), 30) rb_rv_index = min(math.ceil((rb_base + ((12 * 1) * .40)) * 1), 60) wr_rv_index = min(math.ceil((wr_base + ((12 * 1) * .55)) * 1), 96) te_rv_index = min(math.ceil((te_base + ((12 * 1) * .05)) * 1), 30) print(f"Need {qb_rv_index} for QB in {12} teams with type {league_settings['TYPE']}") print(f"Need {rb_rv_index} for RB in {12} teams with type {league_settings['TYPE']}") print(f"Need {wr_rv_index} for WR in {12} teams with type {league_settings['TYPE']}") print(f"Need {te_rv_index} for TE in {12} teams with type {league_settings['TYPE']}") pos_reqs = { 'QB': qb_rv_index, 'RB': rb_rv_index, 'WR': wr_rv_index, 'TE': te_rv_index, } return pos_reqs def create_halfPpr_rv(frame: pd.DataFrame, pos_reqs: dict) -> dict: rv_dict = {} for positions in ['QB', 'RB', 'WR', 'TE']: rv_dict[f'{positions}'] = frame[frame['Pos'] == positions].head(pos_reqs[positions]).reset_index(drop=True)['halfPpr'].tail(1).values[0] return rv_dict def create_custom_rv(frame: pd.DataFrame, pos_reqs: dict, league_settings: dict) -> dict: if league_settings['TYPE'] == 'Half PPR': rv_type = 'halfPpr' elif league_settings['TYPE'] == 'PPR': rv_type = 'ppr' elif league_settings['TYPE'] == 'Standard': rv_type = 'standard' elif league_settings['TYPE'] == 'Superflex': rv_type = 'halfPpr' elif league_settings['TYPE'] == 'TE Premium': rv_type = 'ppr' rv_dict = {} for positions in ['QB', 'RB', 'WR', 'TE']: rv_dict[f'{positions}'] = frame[frame['Pos'] == positions].head(pos_reqs[positions]).reset_index(drop=True)[rv_type].tail(1).values[0] return rv_dict def assign_vorp_scoring(frame: pd.DataFrame, halfPpr_rv: dict, custom_rv: dict, league_settings: dict, pos_vorp_limiters: dict) -> pd.DataFrame: if league_settings['TYPE'] == 'Half PPR': rv_type = 'halfPpr' elif league_settings['TYPE'] == 'PPR': rv_type = 'ppr' elif league_settings['TYPE'] == 'Standard': rv_type = 'standard' elif league_settings['TYPE'] == 'Superflex': rv_type = 'halfPpr' elif league_settings['TYPE'] == 'TE Premium': rv_type = 'ppr' if league_settings['QB'] > 1: pos_vorp_limiters['QB'] = .9 if league_settings['TE'] > 1: pos_vorp_limiters['TE'] = .9 vorp_frame = pd.DataFrame() for positions in ['QB', 'RB', 'WR', 'TE']: pos_frame = frame[frame['Pos'] == positions] pos_frame = pos_frame[pos_frame['Rank'] != 0] pos_frame = pos_frame.sort_values(by='Rank', ascending=True).reset_index(drop=True) pos_frame['halfPpr_rv'] = halfPpr_rv[positions] pos_frame['custom_rv'] = custom_rv[positions] pos_frame['halfPpr_VORP'] = pos_frame['halfPpr'] - halfPpr_rv[positions] pos_frame['custom_VORP'] = pos_frame[rv_type] - custom_rv[positions] print(pos_frame[['Name', 'halfPpr', 'custom_rv', 'halfPpr_VORP', 'custom_VORP']].head(20)) vorp_frame = pd.concat([vorp_frame, pos_frame]).reset_index(drop=True) vorp_frame['halfPpr_vorp_rank'] = vorp_frame['halfPpr_VORP'].rank(method='max', ascending=False) vorp_frame['custom_vorp_rank'] = vorp_frame['custom_VORP'].rank(method='max', ascending=False) vorp_frame['vorp_diff'] = np.where(vorp_frame['halfPpr_VORP'] == vorp_frame['custom_VORP'], 0, vorp_frame['halfPpr_vorp_rank'] - vorp_frame['custom_vorp_rank']) for positions in ['QB', 'RB', 'WR', 'TE']: vorp_frame.loc[vorp_frame['Pos'] == positions, 'Rank_Adjust'] = (vorp_frame['Rank'] - (vorp_frame['vorp_diff'] * pos_vorp_limiters[positions])).astype(float) vorp_frame['custom_rank'] = vorp_frame['Rank_Adjust'].rank(method='first', ascending=True).astype(int) vorp_frame['pos_rank'] = vorp_frame.groupby('Pos')['custom_rank'].rank(method='first', ascending=True).astype(int) vorp_frame['pos_designation'] = vorp_frame['Pos'] + vorp_frame['pos_rank'].astype(str) pos_des_dict = dict(zip(vorp_frame['pos_designation'], vorp_frame['Name'])) orig_rank_dict = dict(zip(vorp_frame['Name'], vorp_frame['pos_designation'])) half_ppr_match_dict = dict(zip(vorp_frame['pos_designation'], vorp_frame['halfPpr'])) custom_match_dict = dict(zip(vorp_frame['pos_designation'], vorp_frame[rv_type])) for pos in ['QB', 'RB', 'WR', 'TE']: print(vorp_frame[vorp_frame['Pos'] == pos].head(20)) return pos_des_dict, orig_rank_dict, half_ppr_match_dict, custom_match_dict def assign_vorp_roster(frame: pd.DataFrame, halfPpr_rv: dict, custom_rv: dict, pos_vorp_limiters: dict, half_ppr_match_dict: dict, custom_match_dict: dict, orig_rank_dict: dict) -> pd.DataFrame: vorp_frame = pd.DataFrame() for positions in ['QB', 'RB', 'WR', 'TE']: pos_frame = frame[frame['Pos'] == positions] pos_frame = pos_frame[pos_frame['Rank'] != 0] pos_frame = pos_frame.sort_values(by='Rank', ascending=True).reset_index(drop=True) pos_frame['ranker_rank'] = pos_frame['Rank'].rank(method='first', ascending=True).astype(int) pos_frame['pos_rank_init'] = pos_frame['Pos'] + pos_frame['ranker_rank'].astype(str) pos_frame['scoring_rank'] = pos_frame['Name'].map(orig_rank_dict) pos_frame['halfPpr_lu'] = pos_frame['pos_rank_init'].map(half_ppr_match_dict) pos_frame['custom_lu'] = pos_frame['pos_rank_init'].map(custom_match_dict) pos_frame['halfPpr_rv'] = halfPpr_rv[positions] pos_frame['custom_rv'] = custom_rv[positions] pos_frame['halfPpr_VORP'] = pos_frame['halfPpr_lu'] - pos_frame['halfPpr_rv'] pos_frame['custom_VORP'] = pos_frame['custom_lu'] - pos_frame['custom_rv'] vorp_frame = pd.concat([vorp_frame, pos_frame]).reset_index(drop=True) vorp_frame['halfPpr_vorp_rank'] = vorp_frame['halfPpr_VORP'].rank(method='max', ascending=False) vorp_frame['custom_vorp_rank'] = vorp_frame['custom_VORP'].rank(method='max', ascending=False) vorp_frame['vorp_diff'] = np.where(vorp_frame['halfPpr_VORP'] == vorp_frame['custom_VORP'], 0, vorp_frame['halfPpr_vorp_rank'] - vorp_frame['custom_vorp_rank']) for positions in ['QB', 'RB', 'WR', 'TE']: vorp_frame.loc[vorp_frame['Pos'] == positions, 'Rank_Adjust'] = (vorp_frame['Rank'] - (vorp_frame['vorp_diff'] * pos_vorp_limiters[positions])).astype(float) vorp_frame['custom_rank'] = vorp_frame['Rank_Adjust'].rank(method='first', ascending=True).astype(int) vorp_frame['pos_rank'] = vorp_frame.groupby('Pos')['custom_rank'].rank(method='first', ascending=True).astype(int) vorp_frame['pos_des'] = vorp_frame['Pos'] + vorp_frame['pos_rank'].astype(str) return vorp_frame.sort_values(by='custom_rank', ascending=True) def main(): st.title("Fantasy Football VORP Calculator") st.write("Configure your league settings and analyze player values") # Get user configuration user_league_settings, user_flex_percentiles, user_flex_multipliers, user_pos_vorp_limiters = create_user_config_interface() projections_df = load_projections_data(Dwain_proj) ranks_dict = load_ranks_data(dwain_ranks) # Create position frames position_df = create_position_frames(projections_df, ranks_dict) # Calculate position requirements base_pos_reqs = designate_base_position_reqs() custom_pos_reqs = designate_custom_position_reqs(user_league_settings, user_flex_percentiles, user_flex_multipliers) # Calculate replacement values halfPpr_rv = create_halfPpr_rv(position_df, base_pos_reqs) custom_scoring_rv = create_custom_rv(position_df, base_pos_reqs, user_league_settings) custom_roster_rv = create_custom_rv(position_df, custom_pos_reqs, user_league_settings) # Calculate VORP and rankings pos_des_dict, orig_rank_dict, half_ppr_match_dict, custom_match_dict = assign_vorp_scoring(position_df, halfPpr_rv, custom_scoring_rv, user_league_settings, user_pos_vorp_limiters) final_df = assign_vorp_roster(position_df, halfPpr_rv, custom_roster_rv, user_pos_vorp_limiters, half_ppr_match_dict, custom_match_dict, orig_rank_dict) final_df = final_df.drop(columns=['SR_ID'], axis=1) final_df.insert(1, 'new_name', final_df['pos_des'].map(pos_des_dict)) final_df = final_df.drop(columns=['pos_rank', 'pos_des', 'pos_rank_init'], axis=1) final_df = final_df.reset_index(drop=True) # Display results st.header("Player Rankings") st.dataframe(final_df, use_container_width=True) blank_left, qb_count_col, rb_count_col, wr_count_col, te_count_col, blank_right = st.columns(6) with qb_count_col: st.subheader("QB Counts") st.write(f"Total QB top 12: {(final_df.loc[0:11, 'Pos'] == 'QB').sum()}, {(((final_df.loc[0:11, 'Pos'] == 'QB').sum() / 12) * 100):.2f}%") st.write(f"Total QB 13 - 24: {(final_df.loc[12:23, 'Pos'] == 'QB').sum()}, {(((final_df.loc[12:23, 'Pos'] == 'QB').sum() / 12) * 100):.2f}%") st.write(f"Total QB 25 - 36: {(final_df.loc[24:35, 'Pos'] == 'QB').sum()}, {(((final_df.loc[24:35, 'Pos'] == 'QB').sum() / 12) * 100):.2f}%") st.write(f"Total QB 37 - 48: {(final_df.loc[36:47, 'Pos'] == 'QB').sum()}, {(((final_df.loc[36:47, 'Pos'] == 'QB').sum() / 12) * 100):.2f}%") with rb_count_col: st.subheader("RB Counts") st.write(f"Total RB top 12: {(final_df.loc[0:11, 'Pos'] == 'RB').sum()}, {(((final_df.loc[0:11, 'Pos'] == 'RB').sum() / 12) * 100):.2f}%") st.write(f"Total RB 13 - 24: {(final_df.loc[12:23, 'Pos'] == 'RB').sum()}, {(((final_df.loc[12:23, 'Pos'] == 'RB').sum() / 12) * 100):.2f}%") st.write(f"Total RB 25 - 36: {(final_df.loc[24:35, 'Pos'] == 'RB').sum()}, {(((final_df.loc[24:35, 'Pos'] == 'RB').sum() / 12) * 100):.2f}%") st.write(f"Total RB 37 - 48: {(final_df.loc[36:47, 'Pos'] == 'RB').sum()}, {(((final_df.loc[36:47, 'Pos'] == 'RB').sum() / 12) * 100):.2f}%") with wr_count_col: st.subheader("WR Counts") st.write(f"Total WR top 12: {(final_df.loc[0:11, 'Pos'] == 'WR').sum()}, {(((final_df.loc[0:11, 'Pos'] == 'WR').sum() / 12) * 100):.2f}%") st.write(f"Total WR 13 - 24: {(final_df.loc[12:23, 'Pos'] == 'WR').sum()}, {(((final_df.loc[12:23, 'Pos'] == 'WR').sum() / 12) * 100):.2f}%") st.write(f"Total WR 25 - 36: {(final_df.loc[24:35, 'Pos'] == 'WR').sum()}, {(((final_df.loc[24:35, 'Pos'] == 'WR').sum() / 12) * 100):.2f}%") st.write(f"Total WR 37 - 48: {(final_df.loc[36:47, 'Pos'] == 'WR').sum()}, {(((final_df.loc[36:47, 'Pos'] == 'WR').sum() / 12) * 100):.2f}%") with te_count_col: st.subheader("TE Counts") st.write(f"Total TE top 12: {(final_df.loc[0:11, 'Pos'] == 'TE').sum()}, {(((final_df.loc[0:11, 'Pos'] == 'TE').sum() / 12) * 100):.2f}%") st.write(f"Total TE 13 - 24: {(final_df.loc[12:23, 'Pos'] == 'TE').sum()}, {(((final_df.loc[12:23, 'Pos'] == 'TE').sum() / 12) * 100):.2f}%") st.write(f"Total TE 25 - 36: {(final_df.loc[24:35, 'Pos'] == 'TE').sum()}, {(((final_df.loc[24:35, 'Pos'] == 'TE').sum() / 12) * 100):.2f}%") st.write(f"Total TE 37 - 48: {(final_df.loc[36:47, 'Pos'] == 'TE').sum()}, {(((final_df.loc[36:47, 'Pos'] == 'TE').sum() / 12) * 100):.2f}%") # Position breakdown st.header("Position Breakdown") for pos in ['QB', 'RB', 'WR', 'TE']: pos_df = final_df[final_df['Pos'] == pos].head(50) st.subheader(f"Top {pos}s") st.dataframe(pos_df, use_container_width=True) if __name__ == "__main__": main()