---
title: "ESPN: Basics"
output: rmarkdown::html_vignette
author: Tan Ho
date: "`r Sys.Date()`"
vignette: >
%\VignetteIndexEntry{ESPN: Basics}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
options(dplyr.summarise.inform = FALSE,
rmarkdown.html_vignette.check_title = FALSE)
eval <- TRUE
tryCatch(expr = {
download.file("https://github.com/ffverse/ffscrapr-tests/archive/1.4.7.zip","f.zip")
unzip('f.zip', exdir = ".")
httptest::.mockPaths(new = "ffscrapr-tests-1.4.7")},
warning = function(e) eval <<- FALSE,
error = function(e) eval <<- FALSE)
httptest::use_mock_api()
```
In this vignette, I'll walk through how to get started with a basic dynasty value analysis on ESPN, pulling in roster data.
We'll start by loading the packages:
```{r setup, message=FALSE, eval = eval}
library(ffscrapr)
library(dplyr)
library(tidyr)
```
In ESPN, you can find the league ID by looking in the URL - it's the number immediately after ?leagueId in this example URL: https://fantasy.espn.com/football/team?leagueId=899513&seasonId=2020
Let's set up a connection to this league:
```{r eval = eval}
sucioboys <- espn_connect(season = 2020, league_id = 899513)
sucioboys
```
I've done this with the `espn_connect()` function, although you can also do this from the `ff_connect()` call - they are equivalent. Most if not all of the remaining functions after this point are prefixed with "ff_".
Cool! Let's have a quick look at what this league is like.
```{r eval = eval}
sucioboys_summary <- ff_league(sucioboys)
str(sucioboys_summary)
```
Okay, so it's the Sucio Boys league, it's a 2QB league with 12 teams, half ppr scoring, and rosters about 240 players.
Let's grab the rosters now.
```{r eval = eval}
sucioboys_rosters <- ff_rosters(sucioboys)
head(sucioboys_rosters) # quick snapshot of rosters
```
## Values
Cool! Let's pull in some additional context by adding DynastyProcess player values.
```{r eval = eval}
player_values <- dp_values("values-players.csv")
# The values are stored by fantasypros ID since that's where the data comes from.
# To join it to our rosters, we'll need playerID mappings.
player_ids <- dp_playerids() %>%
select(espn_id,fantasypros_id) %>%
filter(!is.na(espn_id),!is.na(fantasypros_id))
# We'll be joining it onto rosters, so we can trim down the values dataframe
# to just IDs, age, and values
player_values <- player_values %>%
left_join(player_ids, by = c("fp_id" = "fantasypros_id")) %>%
select(espn_id,age,ecr_2qb,ecr_pos,value_2qb)
# we can join the roster's player_ids on the values' espn_id, with a bit of a type conversion first
sucioboys_values <- sucioboys_rosters %>%
mutate(player_id = as.character(player_id)) %>%
left_join(player_values, by = c("player_id"="espn_id")) %>%
arrange(franchise_id,desc(value_2qb))
head(sucioboys_values)
```
Let's do some team summaries now!
```{r eval = eval}
value_summary <- sucioboys_values %>%
group_by(franchise_id,franchise_name,pos) %>%
summarise(total_value = sum(value_2qb,na.rm = TRUE)) %>%
ungroup() %>%
group_by(franchise_id,franchise_name) %>%
mutate(team_value = sum(total_value)) %>%
ungroup() %>%
pivot_wider(names_from = pos, values_from = total_value) %>%
arrange(desc(team_value)) %>%
select(franchise_id,franchise_name,team_value,QB,RB,WR,TE)
value_summary
```
So with that, we've got a team summary of values! I like applying some context, so let's turn these into percentages - this helps normalise it to your league environment.
```{r eval = eval}
value_summary_pct <- value_summary %>%
mutate_at(c("team_value","QB","RB","WR","TE"),~.x/sum(.x)) %>%
mutate_at(c("team_value","QB","RB","WR","TE"),round, 3)
value_summary_pct
```
Armed with a value summary like this, we can see team strengths and weaknesses pretty quickly, and figure out who might be interested in your positional surpluses and who might have a surplus at a position you want to look at.
## Age
Another question you might ask: what is the average age of any given team?
I like looking at average age by position, but weighted by dynasty value. This helps give a better idea of age for each team - including who might be looking to offload an older veteran!
```{r eval = eval}
age_summary <- sucioboys_values %>%
filter(pos %in% c("QB","RB","WR","TE")) %>%
group_by(franchise_id,pos) %>%
mutate(position_value = sum(value_2qb,na.rm=TRUE)) %>%
ungroup() %>%
mutate(weighted_age = age*value_2qb/position_value,
weighted_age = round(weighted_age, 1)) %>%
group_by(franchise_id,franchise_name,pos) %>%
summarise(count = n(),
age = sum(weighted_age,na.rm = TRUE)) %>%
pivot_wider(names_from = pos,
values_from = c(age,count))
age_summary
```
## Next steps
In this vignette, I've used only a few functions: ff_connect, ff_league, ff_rosters, and dp_values. Now that you've gotten this far, why not check out some of the other possibilities?
```{r include = FALSE}
httptest::stop_mocking()
unlink(c("ffscrapr-tests-1.4.7","f.zip"), recursive = TRUE, force = TRUE)
```