Sunnuntaiaamuna, työvuorolistat ovat aikeissa lukita varhain iltapäivällä liuskekivi, ja olet päättämässä kahden yhdeksännen tier WRs että WR3 paikka. Se on viikko 3, ne ovat molemmat waiver wire epätoivoinen poimintoja et ole ollut aikaa tutkia, ja rehellisesti sanottuna, sinulla on muita kaloja paistaa tänään. Katso: ESPN:n ennustettu pistemäärä toiselle kaverille on 7, toiselle kaverille 8. Päätät valita 8:n ja ajattelet: ”Tuon ennustetun pistemäärän täytyy merkitä jotakin, eikö niin?”
tl;dr Tuo ennustettu pistemäärä ei merkitse oikeastaan mitään, ja voimme näyttää sen käyttämällä (dokumentoimatonta) ESPN Fantasy API:ta ja hieman Pythonia.
Hieman taustaa
Mike Clay on ESPN:n fantasy-ennusteiden verhon takana oleva mies. Hän vannoo, että hänellä on ”pitkä prosessi”, joka sisältää ”tilastollisia laskelmia ja subjektiivisia syötteitä”. Tarkoitan, että hänelle maksetaan palkkaa ja minä kirjoitan blogipostauksia, joten en voi vihata liikaa sitä, mikä tämä mystinen tilastollinen prosessi sitten onkaan.
Sitä huolimatta on tehty monia analyysejä, joissa ESPN:n ennusteita verrataan muihin sivustoihin kautta linjan kiihkeistä reddit-postauksista NYT:n blogipostauksiin.
Konsensus näyttää olevan, ESPN:n ennusteet eivät ole kovin hyviä, perustuen ”tarkkuuden” ja R-kvadrantin kaltaisiin mittareihin, jotka yrittävät kvantifioida yleistä virhettä yhdellä yhteenvetotilastolla.
Mutta huomaan myös, että on hyvin vähän tietoa siitä, miten tämän voi tarkistaa itselleen. Tämä sivusto footballanalytics.net linkittää hienoihin R-skripteihin, mutta en nähnyt, että mikään niistä nappaisi ESPN:n ennusteita nimenomaan (voin tosin olla väärässä).
Exploring …
ESPN ylläpitää tällä hetkellä yhtä historiallista kauden ennusteita, joten nappaamme vuoden 2018 ja katsomme, mitä löydämme.
Hyödynnämme ESPN Fantasy API:ta, jonka käyttöä käsittelen täällä.
Lyhyesti sanottuna lähetämme ESPN:lle saman GET-pyynnön, jonka sen verkkosivusto lähettää omille palvelimilleen, kun siirrymme historiallisen liigan sivulle. Voit salakuunnella, miten nämä pyynnöt muodostetaan, käyttämällä Safarin Web Developer -työkaluja tai välityspalvelua, kuten Charlesia tai Fiddleriä.
Ennen kuin kirjoitamme koodia, jolla nappaamme kaikki tarvitsemamme tiedot, tutustutaanpa pieneen pätkään:
import requestsswid = 'YOUR_SWID'espn_s2 = 'LONG_ESPN_S2_KEY'league_id = 123456season = 2018week = 5url = 'https://fantasy.espn.com/apis/v3/games/ffl/seasons/' + \ str(season) + '/segments/0/leagues/' + str(league_id) + \ '?view=mMatchup&view=mMatchupScore'r = requests.get(url, params={'scoringPeriodId': week}, cookies={"SWID": swid, "espn_s2": espn})d = r.json()
Tämä on selitetty hieman yksityiskohtaisemmin edellisessä postauksessani, mutta ideana on se, että lähetämme pyynnön ESPN:n API:lle tiettyä näkymää varten tiettyyn liigaan, viikkoon ja kauteen liittyen, joka antaa meille täydelliset matchup/boxscore-infot, mukaan lukien ennakoidut pisteet. Evästeitä tarvitaan vain yksityisiä liigoja varten, ja jälleen kerran käsittelen sitä tässä.
Jos navigoit JSON-rakenteen läpi, huomaat, että jokaisella fantasy-joukkueella on roster
sen pelaajista, ja jokaisella pelaajalla on listaus sen stats
pelaajista.
(Jälleen kerran, mukava tapa navigoida tässä rakenteessa on käyttää Safarin Web Developer -työkaluja: mene fantasialiigasi kerhohuoneen kiinnostavalle sivulle, avaa Web Developer -työkalut, siirry kohtaan Resurssit ja etsi sitten XHR:ien alta objekti, jossa on liigasi tunnus. Tämä on JSONin raakateksti … vaihda ”Response” muotoon ”JSON” pienellä otsikkoalueella, jotta saat käyttäjäystävällisemmän explorer-tyylisen käyttöliittymän.)
Grabbing all 2018 Projections
Hieman piilossa, mutta tässä alarakenteessa on ennustetut ja todelliset fantasiapisteet jokaiselle pelaajalle jokaisessa rosterissa.
Havaitsin, että tietyn pelaajan stats
-listalla on 5-6 merkintää, joista yksi on aina ennustettu pistemäärä ja toinen todellinen. Projisoitu pistemäärä tunnistetaan statSourceId=1
:lla, todellinen pistemäärä statSourceId=0
:llä.
Käytetään tätä havaintoa rakentaaksemme joukon silmukoita, jotka lähettävät GET-pyynnöt kullekin viikolle ja poimivat sitten jokaisen pelaajan jokaisen ennustetun/todellisen pistemäärän kustakin pelaajaluettelosta.
import requestsimport pandas as pdleague_id = 123456season = 2018slotcodes = { 0 : 'QB', 2 : 'RB', 4 : 'WR', 6 : 'TE', 16: 'Def', 17: 'K', 20: 'Bench', 21: 'IR', 23: 'Flex'}url = 'https://fantasy.espn.com/apis/v3/games/ffl/seasons/' + \ str(season) + '/segments/0/leagues/' + str(league_id) + \ '?view=mMatchup&view=mMatchupScore'data = print('Week ', end='')for week in range(1, 17): print(week, end=' ') r = requests.get(url, params={'scoringPeriodId': week}, cookies={"SWID": swid, "espn_s2": espn}) d = r.json() for tm in d: tmid = tm for p in tm: name = p slot = p pos = slotcodes # injured status (need try/exc bc of D/ST) inj = 'NA' try: inj = p except: pass # projected/actual points proj, act = None, None for stat in p: if stat != week: continue if stat == 0: act = stat elif stat == 1: proj = stat data.append()print('\nComplete.')data = pd.DataFrame(data, columns=)
Week 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Complete.
Tuloksena saadaan jotain tällaista:
data.head()
Week Team Player Slot Pos Status Proj Actual0 1 1 Leonard Fournette 2 RB QUESTIONABLE 13.891825 5.01 1 1 Christian McCaffrey 2 RB ACTIVE 11.067053 7.02 1 1 Derrick Henry 20 Bench ACTIVE 10.271163 2.03 1 1 Josh Gordon 4 WR OUT 6.153141 7.04 1 1 Philip Rivers 0 QB QUESTIONABLE 26.212294 42.0
Kyllä, kyllä, tämä on vain pelaajia, jotka ovat pelaajaluetteloissa, joten emme kaappaa yhtään vapaata agenttia … mutta sen pitäisi ainakin antaa meille käsitys ESPN:n ennusteiden tarkkuudesta, toistaiseksi.
Plotataanpa ”Proj” vastaan ”Actual” muutamalle eri pelipaikalle ja pidetään peukut pystyssä …
fig, axs = plt.subplots(1,3, sharey=True, figsize=(12, 4))for i, pos in enumerate(): (data .query('Pos == @pos') .pipe((axs.scatter, 'data'), x='Proj', y='Actual', s=50, c='b', alpha=0.5) ) axs.plot(, , 'k--') axs.set(xlim=, ylim=, xlabel='Projected', title=pos)axs.set_ylabel('Actual')plt.tight_layout()plt.show()
Um, ei hyvä. Tässä voisi tehdä tilastollisia testejä, mutta minun kouluttamattomaan silmääni näyttää siltä, että nuo ennustetut pisteet voisivat yhtä hyvin olla peräisin tasaisesta jakaumasta.
Mahdollisesti se on parempi tietyillä viikoilla? Myöhemmin kaudella ehkä? Piirretäänpä kokonaisvirhe viikoittain ja asemittain. Tästä koodista tulee hieman hakkeroitua 🙁 mutta olen valmis elämään sen kanssa:
fig, axs = plt.subplots(1,3, sharey=True, figsize=(13,4))data = data - datadata = pd.cut(data, bins=4, labels=)cols = sns.color_palette('Blues')# dummy plots for a legendfor k,cat in enumerate(): axs.plot(,, c=cols, label='Wk ' + cat)axs.legend()for i, pos in enumerate(): for cat in range(4): t = data.query('Pos == @pos & Cat == @cat') sns.kdeplot(t, color=cols, ax=axs, legend=False) axs.set(xlabel='Actual - Proj', title=pos) plt.show()
Mahdollisesti on taipumusta yliprojisoida myöhemmin kaudella, mutta kokonaisuutena en sanoisi tässäkään mitään. (Huomaa, että näin menetimme jonkin verran tietoa siitä, onko virhe enemmän vai vähemmän korkeilla vs. matalilla ennusteilla)
Katsoisin seuraavaksi pelaajien pisteiden aikasarjoja. Maalaisjärki sanoo, että paras tapa arvata, mitä pelaaja tekee pisteitä ensi viikolla, on vain silmäillä hänen viimeisiä 4-5 viikkoaan … kuinka luotettava strategia tämä on?
Tässä postauksessa yritän tarkistaa ESPN:n ennusteita rosteritasolla – ehkä yksittäiset ennusteet eivät ole vaikuttavia, mutta kokonaisuutena ne alkavat maagisesti auttaa? (Spoileri: ei oikeastaan.)
Kirjoittanut 5. elokuuta 2019 Steven Morse