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.

MFL: Basics

Tan Ho

2023-02-11

In this vignette, I’ll walk through how to get started with a basic dynasty value analysis on MFL.

We’ll start by loading the packages:

  library(ffscrapr)
  library(dplyr)
  library(tidyr)

Set up the connection to the league:

ssb <- mfl_connect(season = 2020, 
                   league_id = 54040, # from the URL of your league
                   rate_limit_number = 3, 
                   rate_limit_seconds = 6)
ssb
#> <MFL connection 2020_54040>
#> List of 5
#>  $ platform   : chr "MFL"
#>  $ season     : num 2020
#>  $ league_id  : chr "54040"
#>  $ APIKEY     : NULL
#>  $ auth_cookie: NULL
#>  - attr(*, "class")= chr "mfl_conn"

I’ve done this with the mfl_connect() function, although you can also do this from the ff_connect() call - they are equivalent. Most if not all of the remaining functions are prefixed with “ff_”.

Cool! Let’s have a quick look at what this league is like.

ssb_summary <- ff_league(ssb)

str(ssb_summary)
#> tibble [1 × 17] (S3: tbl_df/tbl/data.frame)
#>  $ league_id        : chr "54040"
#>  $ league_name      : chr "The Super Smash Bros Dynasty League"
#>  $ season           : int 2020
#>  $ league_type      : chr NA
#>  $ franchise_count  : num 14
#>  $ qb_type          : chr "1QB"
#>  $ idp              : logi FALSE
#>  $ scoring_flags    : chr "0.5_ppr, TEPrem, PP1D"
#>  $ best_ball        : logi FALSE
#>  $ salary_cap       : logi FALSE
#>  $ player_copies    : num 1
#>  $ years_active     : chr "2018-2021"
#>  $ qb_count         : chr "1"
#>  $ roster_size      : num 33
#>  $ league_depth     : num 462
#>  $ draft_type       : chr " email draft"
#>  $ draft_player_pool: chr "Both"

Okay, so it’s the Smash Bros Dynasty League, it’s a 1QB league with 14 teams, best ball scoring, half ppr and point-per-first-down settings.

Let’s grab the rosters now.

ssb_rosters <- ff_rosters(ssb)

head(ssb_rosters)
#> # A tibble: 6 × 11
#>   franchise_id franc…¹ playe…² playe…³ pos   team    age roste…⁴ drafted draft…⁵
#>   <chr>        <chr>   <chr>   <chr>   <chr> <chr> <dbl> <chr>   <chr>   <chr>  
#> 1 0001         Team P… 13189   Engram… TE    NYG    28.4 ROSTER  3.04    2017   
#> 2 0001         Team P… 11680   Landry… WR    CLE    30.2 ROSTER  4.02    2014   
#> 3 0001         Team P… 13645   Smith,… WR    NOS    27.1 ROSTER  18.02   2018   
#> 4 0001         Team P… 12110   Brate,… TE    TBB    31.6 ROSTER  19.04   2014   
#> 5 0001         Team P… 13168   Reynol… WR    LAR    28   ROSTER  20.02   2017   
#> 6 0001         Team P… 13793   Valdes… WR    GBP    28.3 ROSTER  21.04   2018   
#> # … with 1 more variable: draft_round <chr>, and abbreviated variable names
#> #   ¹​franchise_name, ²​player_id, ³​player_name, ⁴​roster_status, ⁵​draft_year
#> # ℹ Use `colnames()` to see all variable names

Values

Cool! Let’s pull in some additional context by adding DynastyProcess player values.

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(mfl_id,fantasypros_id)

player_values <- player_values %>% 
  left_join(player_ids, by = c("fp_id" = "fantasypros_id")) %>% 
  select(mfl_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

ssb_values <- ssb_rosters %>% 
  left_join(player_values, by = c("player_id"="mfl_id")) %>% 
  arrange(franchise_id,desc(value_1qb))

head(ssb_values)
#> # A tibble: 6 × 14
#>   franchise_id franc…¹ playe…² playe…³ pos   team    age roste…⁴ drafted draft…⁵
#>   <chr>        <chr>   <chr>   <chr>   <chr> <chr> <dbl> <chr>   <chr>   <chr>  
#> 1 0001         Team P… 14803   Edward… RB    KCC    23.8 ROSTER  1.01    2020   
#> 2 0001         Team P… 14835   Higgin… WR    CIN    24   ROSTER  Trade   2020   
#> 3 0001         Team P… 14779   Herber… QB    LAC    24.9 ROSTER  2.11    2020   
#> 4 0001         Team P… 14777   Burrow… QB    CIN    26.2 INJURE… 1.14    2020   
#> 5 0001         Team P… 14838   Shenau… WR    JAC    24.4 ROSTER  2.02    2020   
#> 6 0001         Team P… 11680   Landry… WR    CLE    30.2 ROSTER  4.02    2014   
#> # … with 4 more variables: draft_round <chr>, ecr_1qb <dbl>, ecr_pos <dbl>,
#> #   value_1qb <int>, and abbreviated variable names ¹​franchise_name,
#> #   ²​player_id, ³​player_name, ⁴​roster_status, ⁵​draft_year
#> # ℹ Use `colnames()` to see all variable names

Let’s do some team summaries now!

value_summary <- ssb_values %>% 
  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: 14 × 7
#>    franchise_id franchise_name     team_value    QB    RB    TE    WR
#>    <chr>        <chr>                   <int> <int> <int> <int> <int>
#>  1 0010         Team Yoshi              41170  4753 14710  7284 14423
#>  2 0006         Team King Dedede        35184  6458  2513   597 25616
#>  3 0004         Team Ice Climbers       35091   115 19362  2470 13144
#>  4 0009         Team Link               33078  1168 10578  5188 16144
#>  5 0003         Team Donkey Kong        30043  1299  6034  7220 15490
#>  6 0007         Team Kirby              27880  4890 14108   182  8700
#>  7 0005         Team Dr. Mario          27659    17  7137  2586 17919
#>  8 0011         Team Diddy Kong         26143   564 12406  2583 10590
#>  9 0002         Team Simon Belmont      25905    40 11318    12 14535
#> 10 0012         Team Mewtwo             24317   618 17670  1340  4689
#> 11 0013         Team Ness               20004   803 15980  1744  1477
#> 12 0014         Team Luigi              19761  1738  5828  1068 11127
#> 13 0001         Team Pikachu            17651  4323  6293   833  6202
#> 14 0008         Team Bowser             13150  5673  4069    25  3383

So with that, we’ve got a team summary of values! I like applying some context, so let’s turn these into percentages.

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
#> # A tibble: 14 × 7
#>    franchise_id franchise_name     team_value    QB    RB    TE    WR
#>    <chr>        <chr>                   <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1 0010         Team Yoshi              0.109 0.146 0.099 0.22  0.088
#>  2 0006         Team King Dedede        0.093 0.199 0.017 0.018 0.157
#>  3 0004         Team Ice Climbers       0.093 0.004 0.131 0.075 0.08 
#>  4 0009         Team Link               0.088 0.036 0.071 0.157 0.099
#>  5 0003         Team Donkey Kong        0.08  0.04  0.041 0.218 0.095
#>  6 0007         Team Kirby              0.074 0.151 0.095 0.005 0.053
#>  7 0005         Team Dr. Mario          0.073 0.001 0.048 0.078 0.11 
#>  8 0011         Team Diddy Kong         0.069 0.017 0.084 0.078 0.065
#>  9 0002         Team Simon Belmont      0.069 0.001 0.076 0     0.089
#> 10 0012         Team Mewtwo             0.064 0.019 0.119 0.04  0.029
#> 11 0013         Team Ness               0.053 0.025 0.108 0.053 0.009
#> 12 0014         Team Luigi              0.052 0.054 0.039 0.032 0.068
#> 13 0001         Team Pikachu            0.047 0.133 0.043 0.025 0.038
#> 14 0008         Team Bowser             0.035 0.175 0.027 0.001 0.021

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!

age_summary <- ssb_values %>% 
  group_by(franchise_id,pos) %>% 
  mutate(position_value = sum(value_1qb,na.rm=TRUE)) %>% 
  ungroup() %>% 
  mutate(weighted_age = age*value_1qb/position_value) %>% 
  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: 14 × 10
#> # Groups:   franchise_id, franchise_name [14]
#>    franchi…¹ franc…² age_QB age_RB age_TE age_WR count…³ count…⁴ count…⁵ count…⁶
#>    <chr>     <chr>    <dbl>  <dbl>  <dbl>  <dbl>   <int>   <int>   <int>   <int>
#>  1 0001      Team P…   25.5   24.3   27.7   24.9       4       8       7      14
#>  2 0002      Team S…   26.5   27.1   26.3   26.1       8      11       3       8
#>  3 0003      Team D…   26.5   25.3   33.3   28.7       5       8       7      13
#>  4 0004      Team I…   30.3   27.1   28.3   28.6       5       9       9      13
#>  5 0005      Team D…   37.4   24.8   26.5   26.3       2       7       3      19
#>  6 0006      Team K…   27.4   27.4   28.2   26.8       3      10       7      10
#>  7 0007      Team K…   26.1   26.8   30.5   30.4       4       9       4      17
#>  8 0008      Team B…   27.8   28.4   34.7   29.9       4      11       4      11
#>  9 0009      Team L…   29.0   27.8   30.1   29.9       3      11       5       7
#> 10 0010      Team Y…   29.4   23.9   29.4   27.7       2       6       6      16
#> 11 0011      Team D…   33.1   28.5   25.7   25.1       4      12       6      11
#> 12 0012      Team M…   34.7   25.7   26.2   25.5       5       7       6      13
#> 13 0013      Team N…   34.4   25.3   25.2   27.0       5       9       5      12
#> 14 0014      Team L…   34.2   27.0   25.3   28.8       3      10       7      14
#> # … with abbreviated variable names ¹​franchise_id, ²​franchise_name, ³​count_QB,
#> #   ⁴​count_RB, ⁵​count_TE, ⁶​count_WR

Next steps

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.