YFDashboard / src /pages /1_Keepers.py
Jon Solow
Remove non-backup qbs from subjective list
78f0d03
import os
import numpy as np
import pandas as pd
import streamlit as st
from config import DEFAULT_ICON, LEAGUE_NAME, LEAGUE_NUMBER_TEAMS, KEEPER_DATA_URL
from shared_page import common_page_config
from streamlit_filter import filter_dataframe
def load_player_ids() -> pd.DataFrame:
df = pd.read_csv(r"https://raw.githubusercontent.com/dynastyprocess/data/master/files/db_playerids.csv")
df["merge_id"] = df["yahoo_id"].combine_first(df["stats_id"])
return df
def load_adp() -> pd.DataFrame:
df = pd.read_csv(r"https://raw.githubusercontent.com/dynastyprocess/data/master/files/db_fpecr_latest.csv")
df = df.loc[
df.fp_page == "/nfl/rankings/ppr-superflex-cheatsheets.php",
[
"id",
"ecr",
"sd",
],
]
return df
def convert_ecr_to_round_val(ecr_float: float, round_offset: float = 1.0, pick_offset: float = -1.0) -> float:
# As a float, store pick 1 of round 1 as 1.0
return round_offset + (ecr_float + pick_offset) / LEAGUE_NUMBER_TEAMS
def add_opinionated_keeper_value(df: pd.DataFrame):
# Manual Hack for overranking of backup QBs
df.loc[
df["name"].isin(
[
"Teddy Bridgewater",
"Davis Mills",
"Andy Dalton",
"Tyler Huntley",
"Mike White",
"Colt McCoy",
"Carson Wentz",
"Trey Lance",
"Taylor Heinicke",
]
),
["ecr"],
] = np.nan
df["ecr"] = df["ecr"].apply(convert_ecr_to_round_val)
# Convert sd without offset to show as pure pick diff
df["sd"] = df["sd"].apply(lambda x: convert_ecr_to_round_val(x, 0, 0))
# assumes midround keeper
# fill -99 for players that are not ranked in ecr
df["value_keeper"] = (df["keeper_cost"] + 0.5 - df["ecr"]).fillna(-99)
@st.cache_data(ttl=60 * 60 * 24)
def load_data():
data = pd.read_csv(os.path.join(os.path.dirname(__file__), KEEPER_DATA_URL), index_col=0)
# Hack to get position, replace with better position from yahoo api in future
data["position"] = (
data["eligible_positions"]
.apply(lambda x: x.split(" ")[0])
.str.replace("[", "")
.str.replace("]", "")
.str.replace("'", "")
)
data.columns = data.columns.str.lower()
data.sort_values(["team_name", "keeper_cost"], inplace=True)
teams_list = sorted(list(data["team_name"].unique()))
# Merge player ids
df_player_ids = load_player_ids()
data = data.merge(df_player_ids, how="left", left_on="player_id", right_on="merge_id", suffixes=("", "_ids"))
# Merge ADP
df_adp = load_adp()
data = data.merge(df_adp, how="left", left_on="fantasypros_id", right_on="id", suffixes=("", "_adp"))
add_opinionated_keeper_value(data)
return data, teams_list
def filtered_keeper_dataframe(data: pd.DataFrame, teams_list: list[str]):
teams_selected = st.multiselect("Team:", teams_list, placeholder="Select a user team to filter")
teams_filter = data["team_name"].isin(teams_selected) if teams_selected else data["team_name"].isin(teams_list)
eligible_options = [True, False]
is_eligible_selected = st.multiselect(
"Keeper Eligible:", eligible_options, placeholder="Select True to filter eligible only"
)
eligible_filter = (
data["eligible"].isin(is_eligible_selected) if is_eligible_selected else data["eligible"].isin(eligible_options)
)
is_advanced = st.checkbox("Show Advanced View")
id_cols = [
"team_name",
"headshot_url",
"name",
]
id_cols_advanced = [
"team",
"position",
]
cost_cols = [
"keeper_cost",
"eligible",
]
cost_cols_advanced = [
"years_eligible",
]
adp_cols: list[str] = []
adp_cols_advanced = [
"ecr",
"value_keeper",
]
if is_advanced:
show_columns = id_cols + id_cols_advanced + cost_cols + cost_cols_advanced + adp_cols + adp_cols_advanced
else:
show_columns = id_cols + cost_cols + adp_cols
data_with_filters_applied = data.loc[teams_filter & eligible_filter, show_columns]
filtered_data = filter_dataframe(data_with_filters_applied)
st.dataframe(
filtered_data,
hide_index=True,
height=35 * (len(filtered_data) + 1) + 12,
use_container_width=True,
column_config={
"team_name": st.column_config.TextColumn(label="League Team", help="Name of fantasy League team."),
"headshot_url": st.column_config.ImageColumn(label="", help="Player image"),
"name": st.column_config.TextColumn(label="Name", help="Player's name"),
"team": st.column_config.TextColumn(label="NFL Team"),
"position": st.column_config.TextColumn(label="Position", help="Player's position"),
"keeper_cost": st.column_config.NumberColumn(
label="Keeper Cost", help="Draft Round Cost to keep player. See Rules for details."
),
"eligible": st.column_config.CheckboxColumn(label="Eligible", help="Is player eligible to be keeper?"),
"years_eligible": st.column_config.NumberColumn(
label="Years Eligible",
help="Number of further consecutive seasons player can be kept (subject to maximum of 2)",
),
"ecr": st.column_config.NumberColumn(
label="ECR",
help="Player's average draft round.pick Expert Consensus Rank (ECR) for PPR - Superflex League",
),
"value_keeper": st.column_config.NumberColumn(
label="Value Keeper",
help="Approx. number of draft rounds of keeper value vs ECR PPR - Superflex League",
),
},
)
def get_keeper_app():
keeper_title = f"{LEAGUE_NAME} Keeper Options"
st.set_page_config(page_title=keeper_title, page_icon=DEFAULT_ICON, layout="wide")
common_page_config()
st.title(keeper_title)
data, teams_list = load_data()
with st.container():
filtered_keeper_dataframe(data, teams_list)
if __name__ == "__main__":
get_keeper_app()