The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
In this vignette, I’ll walk through how to get started with a basic dynasty value analysis on Sleeper.
We’ll start by loading the packages:
library(ffscrapr)
library(dplyr)
library(tidyr)
In Sleeper, unlike in other platforms, it’s very unlikely that you’ll remember the league ID - both because most people use the mobile app, and because it happens to be an 18 digit number! It’s a little more natural to start analyses from the username, so let’s start there!
<- sleeper_userleagues("solarpool",2020)
solarpool_leagues #> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
head(solarpool_leagues)
#> # A tibble: 3 × 4
#> league_name league_id franchise_name franch…¹
#> <chr> <chr> <chr> <chr>
#> 1 The JanMichaelLarkin Dynasty League 522458773317046272 solarpool 2028920…
#> 2 DLP Dynasty League 521379020332068864 DLP::thoriyan 2028920…
#> 3 z_dynastyprocess-test 633501761776197632 solarpool 2028920…
#> # … with abbreviated variable name ¹franchise_id
Let’s pull the JML league ID from here for analysis, and set up a Sleeper connection object.
<- solarpool_leagues %>%
jml_id filter(league_name == "The JanMichaelLarkin Dynasty League") %>%
pull(league_id)
# For quick analyses, I'm not above copy-pasting the league ID instead!
jml_id #> [1] "522458773317046272"
<- sleeper_connect(season = 2020, league_id = jml_id)
jml
jml#> <Sleeper connection 2020_522458773317046272>
#> List of 5
#> $ platform : chr "Sleeper"
#> $ season : num 2020
#> $ user_name: NULL
#> $ league_id: chr "522458773317046272"
#> $ user_id : NULL
#> - attr(*, "class")= chr "sleeper_conn"
I’ve done this with the sleeper_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.
<- ff_league(jml)
jml_summary #> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
str(jml_summary)
#> tibble [1 × 16] (S3: tbl_df/tbl/data.frame)
#> $ league_id : chr "522458773317046272"
#> $ league_name : chr "The JanMichaelLarkin Dynasty League"
#> $ season : int 2020
#> $ league_type : chr "dynasty"
#> $ franchise_count: num 12
#> $ qb_type : chr "1QB"
#> $ idp : logi FALSE
#> $ scoring_flags : chr "0.5_ppr"
#> $ best_ball : logi FALSE
#> $ salary_cap : logi FALSE
#> $ player_copies : num 1
#> $ years_active : chr "2019-2020"
#> $ qb_count : chr "1"
#> $ roster_size : int 25
#> $ league_depth : num 300
#> $ prev_league_ids: chr "386236959468675072"
Okay, so it’s the JanMichaelLarkin Dynasty League, it’s a 1QB league with 12 teams, half ppr scoring, and rosters about 300 players.
Let’s grab the rosters now.
<- ff_rosters(jml)
jml_rosters #> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
#> No encoding supplied: defaulting to UTF-8.
head(jml_rosters)
#> # A tibble: 6 × 7
#> franchise_id franchise_name player_id player_name pos team age
#> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
#> 1 1 Fake News 1110 T.Y. Hilton WR IND 33.2
#> 2 1 Fake News 1339 Zach Ertz TE PHI 32.3
#> 3 1 Fake News 1426 DeAndre Hopkins WR ARI 30.7
#> 4 1 Fake News 1825 Jarvis Landry WR CLE 30.2
#> 5 1 Fake News 2025 Albert Wilson WR MIA 30.6
#> 6 1 Fake News 2197 Brandin Cooks WR HOU 29.4
Cool! Let’s pull in some additional context by adding DynastyProcess player values.
<- dp_values("values-players.csv")
player_values
# 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.
<- dp_playerids() %>%
player_ids select(sleeper_id,fantasypros_id)
<- player_values %>%
player_values left_join(player_ids, by = c("fp_id" = "fantasypros_id")) %>%
select(sleeper_id,ecr_1qb,ecr_pos,value_1qb)
# Drilling down to just 1QB values and IDs, we'll be joining it onto rosters and don't need the extra stuff
<- jml_rosters %>%
jml_values left_join(player_values, by = c("player_id"="sleeper_id")) %>%
arrange(franchise_id,desc(value_1qb))
head(jml_values)
#> # A tibble: 6 × 10
#> franchise_id franc…¹ playe…² playe…³ pos team age ecr_1qb ecr_pos value…⁴
#> <chr> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <int>
#> 1 1 Fake N… 4866 Saquon… RB NYG 26 3.4 2.8 9694
#> 2 1 Fake N… 4199 Aaron … RB GB 28.2 21 10.3 6410
#> 3 1 Fake N… 1426 DeAndr… WR ARI 30.7 21.1 7.2 6395
#> 4 1 Fake N… 4037 Chris … WR TB 27 33.7 13.8 4756
#> 5 1 Fake N… 4098 Kareem… RB CLE 27.5 63.7 23.7 2350
#> 6 1 Fake N… 5022 Dallas… TE PHI 27.6 83.2 7.8 1486
#> # … with abbreviated variable names ¹franchise_name, ²player_id, ³player_name,
#> # ⁴value_1qb
Let’s do some team summaries now!
<- jml_values %>%
value_summary group_by(franchise_id,franchise_name,pos) %>%
summarise(total_value = sum(value_1qb,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))
value_summary#> # A tibble: 12 × 8
#> franchise_id franchise_name team_value QB RB TE WR FB
#> <chr> <chr> <int> <int> <int> <int> <int> <int>
#> 1 3 solarpool 45406 7664 23920 529 13293 NA
#> 2 4 The FANTom Menace 41754 3051 7594 1820 29289 NA
#> 3 11 Permian Panthers 40081 3889 9902 6997 19293 NA
#> 4 1 Fake News 37716 1505 19221 2730 14260 NA
#> 5 8 Hocka Flocka 37314 1234 20459 2511 13110 NA
#> 6 12 jaydk 33981 1696 17692 2936 11657 NA
#> 7 5 Barbarians 32614 3770 19492 4629 4723 NA
#> 8 6 sox05syd 30780 4329 5614 8136 12701 NA
#> 9 9 ZPMiller97 24697 2941 12782 998 7976 NA
#> 10 2 KingGabe 19931 41 6327 15 13548 NA
#> 11 7 Flipadelphia05 18140 1951 4799 789 10601 NA
#> 12 10 JMLarkin 14197 336 67 884 12908 2
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.
<- value_summary %>%
value_summary_pct 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#> # A tibble: 12 × 8
#> franchise_id franchise_name team_value QB RB TE WR FB
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
#> 1 3 solarpool 0.121 0.236 0.162 0.016 0.081 NA
#> 2 4 The FANTom Menace 0.111 0.094 0.051 0.055 0.179 NA
#> 3 11 Permian Panthers 0.106 0.12 0.067 0.212 0.118 NA
#> 4 1 Fake News 0.1 0.046 0.13 0.083 0.087 NA
#> 5 8 Hocka Flocka 0.099 0.038 0.138 0.076 0.08 NA
#> 6 12 jaydk 0.09 0.052 0.12 0.089 0.071 NA
#> 7 5 Barbarians 0.087 0.116 0.132 0.14 0.029 NA
#> 8 6 sox05syd 0.082 0.134 0.038 0.247 0.078 NA
#> 9 9 ZPMiller97 0.066 0.091 0.086 0.03 0.049 NA
#> 10 2 KingGabe 0.053 0.001 0.043 0 0.083 NA
#> 11 7 Flipadelphia05 0.048 0.06 0.032 0.024 0.065 NA
#> 12 10 JMLarkin 0.038 0.01 0 0.027 0.079 2
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.
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!
<- jml_values %>%
age_summary group_by(franchise_id,pos) %>%
mutate(position_value = sum(value_1qb,na.rm=TRUE)) %>%
ungroup() %>%
mutate(weighted_age = age*value_1qb/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#> # A tibble: 12 × 12
#> # Groups: franchise_id, franchise_name [12]
#> franchis…¹ franc…² age_QB age_RB age_TE age_WR age_FB count…³ count…⁴ count…⁵
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <int> <int> <int>
#> 1 1 Fake N… 30.4 27.1 27.2 29.1 NA 3 8 7
#> 2 10 JMLark… 30.1 28.9 27.6 26.8 31.8 3 10 3
#> 3 11 Permia… 25.7 24.7 33.2 27.1 NA 4 9 7
#> 4 12 jaydk 33.8 27.3 27.6 29.5 NA 4 7 5
#> 5 2 KingGa… 30.5 24.1 28.8 23.9 NA 5 4 3
#> 6 3 solarp… 27.1 27.2 28.1 29.3 NA 5 10 4
#> 7 4 The FA… 30.4 25 25.4 28.5 NA 5 14 2
#> 8 5 Barbar… 26.7 26.1 30.4 27.9 NA 3 10 6
#> 9 6 sox05s… 25.5 25.7 28.8 26.9 NA 3 5 9
#> 10 7 Flipad… 34.6 27.3 28.9 28.4 NA 2 10 4
#> 11 8 Hocka … 33 25.8 25.5 25.1 NA 3 6 4
#> 12 9 ZPMill… 26 25.5 28.3 26.7 NA 3 9 4
#> # … with 2 more variables: count_WR <int>, count_FB <int>, and abbreviated
#> # variable names ¹franchise_id, ²franchise_name, ³count_QB, ⁴count_RB,
#> # ⁵count_TE
#> # ℹ Use `colnames()` to see all variable names
In this vignette, I’ve used ~three functions: ff_connect, ff_league, and ff_rosters. Now that you’ve gotten this far, why not check out some of the other possibilities?
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.