<jupyter_start><jupyter_text>Week 1 recap[nbviewer](https://nbviewer.jupyter.org/github/joeeoj/fantasy-football/blob/main/week1_recap.ipynb)<jupyter_code>import json
from pathlib import Path
from typing import List

import altair as alt
from espn_api.football import League
import pandas as pd
FNAME = './data/week_01_points.json'
DATA_DIR = Path.cwd() / 'data'

TEAMS = {
    1: 'Fully  Maccinated',
    2: "Rippin' Swigs",
    3: 'Seattle Fantasy Team',
    10: '<NAME>',
    11: 'Raiders Are Good',
    12: 'Herb Your Enthusiasm',
    13: 'Too Many Cooks',
    15: 'Elite starts  with Eli',
    16: 'Draftin Herbert First Pick',
    17: 'Scooty Lewis and the News',
    18: 'Team <NAME>',
    19: 'Federal Way Yu',
}

LEAGUE_ID = 17588244
YEAR = 2021
def load_or_query_draft_amounts() -> dict:
    """Loads draft data from ESPN and saves or loads from file"""
    fout = DATA_DIR / 'draft_bid_amounts.json'

    if fout.exists():
        print('loading file on disk')
        with open(fout) as f:
            draft_amounts = json.load(f)
    else:
        print('pulling data from ESPN')
        league = League(league_id=LEAGUE_ID, year=YEAR)
        draft = league.draft
        draft_amounts = {str(p.playerId): p.bid_amount for p in draft}
        assert len(draft_amounts) == 180

        with open(fout, 'wt') as f:
            json.dump(draft_amounts, f)

    return draft_amounts

DRAFT_AMOUNTS = load_or_query_draft_amounts()
def flatten_json(teams: List[dict]) -> pd.DataFrame:
    flattened = []
    for team_id, team in teams.items():
        for pos, players in team.items():
            for p in players:
                row = []
                row = [team_id] + list(p.values())
                flattened.append(row)

    df = pd.DataFrame(flattened, columns=['fantasy_team_id', 'player_id', 'name', 'team', 'pos',
                                          'slot_position', 'injury_status', 'actual_points',
                                          'projected_points', 'points_breakdown'])
    # drop for now
    df = df.drop('points_breakdown', axis=1)
    df['points_diff'] = df['actual_points'] - df['projected_points']
    df['fantasy_team_name'] = df['fantasy_team_id'].apply(lambda s: TEAMS.get(int(s)))
    df['draft_price'] = df['player_id'].apply(lambda s: DRAFT_AMOUNTS.get(str(s), 0))

    reordered = ['fantasy_team_id', 'fantasy_team_name', 'player_id', 'name', 'team',
                 'pos', 'slot_position', 'injury_status', 'actual_points',
                 'projected_points', 'points_diff', 'draft_price']

    return df[reordered]
with open(FNAME) as f:
    teams = json.load(f)

df = flatten_json(teams)

df.head()<jupyter_output><empty_output><jupyter_text>Projects and actual pointsBinned by original draft price<jupyter_code>m = (df['projected_points'] > 0) #& (df['slot_position'] == 'WR')

tooltip_cols = ['name', 'team', 'slot_position', 'projected_points', 'actual_points',
                'points_diff', 'fantasy_team_name', 'draft_price']

chart = (alt.Chart(df[m])
 .mark_point()
 .encode(x='projected_points:Q', y='actual_points:Q',
         color='pos',
         size='draft_price',
         tooltip=tooltip_cols)
 .properties(width=500, height=500))

chart.interactive() + chart.transform_regression('projected_points', 'actual_points').mark_line()<jupyter_output><empty_output><jupyter_text>winners and losersTop 20 best and top 20 worst point diffs (actual vs projected)<jupyter_code># players with projected points
m = (df['projected_points'] > 0) #& (df['slot_position'] != 'BE')

top = df[m].sort_values('points_diff', ascending=False).head(20)
bottom = df[m].sort_values('points_diff', ascending=True).head(20)

winners_losers = pd.concat([top, bottom])
tooltip_cols = ['name', 'team', 'slot_position', 'projected_points', 'actual_points',
                'points_diff', 'fantasy_team_name', 'draft_price']

(alt.Chart(winners_losers)
 .mark_bar()
 .encode(x='points_diff', y='name', color='slot_position', tooltip=tooltip_cols)
 .properties(width=400, height=600))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14423076923076922, 'fraction_numerical': 0.015779092702169626, 'mean_word_length': 3.61547212741752, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '158537', 'license': 'MIT', 'n_tokens_mistral': 1457, 'n_tokens_neox': 1376, 'n_words': 300, 'path': 'week1_recap.ipynb', 'repo_name': 'joeeoj/fantasy-football', 'size': '4067'}