ffverse / ffscrapr

R API Client for Fantasy Football League Platforms
https://ffscrapr.ffverse.com
Other
82 stars 21 forks source link

Add defense league points to ff_scoringhistory with new nflfastR defense player stats #387

Open christianlohr9 opened 1 year ago

christianlohr9 commented 1 year ago

Yo Tan,

I just tried to do some fantasy WAR analysis in an IDP league and recognized that's not possible for a specific scoring, because ff_scoringhistory scrapes the calculate_player_stats data.

Maybe it'd be cool to add IDP scoring via the new function for defense stats.

Best regards, Christian

christianlohr9 commented 1 year ago

I found out that you have to adjust the function nflfastr_weekly and add a function .nflfastr_defense_long in script 1_import_nflfastr.R.

I added a stat_type "defense" which provides a df_weekly for defense stats. I'm a noob coder and the PR to nflfastR was already a pain in the ass for me, but you could do it like that for instance:

nflfastr_weekly <- function(seasons = TRUE,
                            type = c("offense", "kicking", "defense")) {

  type <- match.arg(type)

  if (type %in% c("offense", "kicking")) {
    df_weekly <- nflreadr::load_player_stats(seasons = seasons, stat_type = type)
  } else if (type %in% c("defense")) {
    df_weekly <- nflfastR::calculate_player_stats_def(nflfastR::load_pbp(seasons = seasons), weekly =TRUE)
  }

  return(df_weekly)
}

.nflfastr_defense_long <- function(season){
  ps <- nflfastr_weekly(seasons = season, type = "defense") %>%
    dplyr::select(dplyr::any_of(c(
      "season", "week","player_id",
      "def_tackles", "def_tackles_solo", "def_tackles_with_assist", "def_tackle_assist", "def_tackles_for_loss", "def_tackles_for_loss_yards",
      "def_fumbles_forced", "def_fumbles", "def_fumble_recovery_own", "def_fumble_recovery_yards_own", "def_fumble_recovery_opp", "def_fumble_recovery_yards_opp",
      "def_sacks", "def_sack_yards", "def_qb_hit",
      "def_interceptions", "def_interception_yards", "def_pass_defended",
      "def_tds", "def_safety", "def_penalty", "def_penalty_yards"
      )
    )) %>%
    tidyr::pivot_longer(
      names_to = "metric",
      cols = -c("season","week","player_id")
    )

  return(ps)
}
christianlohr9 commented 1 year ago

If I'm correct the only thing in addition would be to add this to ff_scoringhistory.sleeper_conn like this:

ff_scoringhistory.sleeper_conn <- function(conn, season = 1999:nflreadr::most_recent_season(), ...) {
  checkmate::assert_numeric(season, lower = 1999, upper = as.integer(format(Sys.Date(), "%Y")))

  # Pull in scoring rules for that league
  league_rules <-
    ff_scoring(conn) %>%
    dplyr::left_join(
      ffscrapr::nflfastr_stat_mapping %>% dplyr::filter(.data$platform == "sleeper"),
      by = c("event" = "ff_event")
    )

  ros <- .nflfastr_roster(season)

  ps <- bind_rows(
    .nflfastr_offense_long(season), 
    .nflfastr_defense_long(season)
    )

  if("K" %in% league_rules$pos){
    ps <- dplyr::bind_rows(
      ps,
      .nflfastr_kicking_long(season))
  }

  ros %>%
    dplyr::inner_join(ps, by = c("gsis_id"="player_id","season")) %>%
    dplyr::inner_join(league_rules, by = c("metric"="nflfastr_event","pos")) %>%
    dplyr::mutate(points = .data$value * .data$points) %>%
    dplyr::group_by(.data$season, .data$week, .data$gsis_id, .data$sportradar_id) %>%
    dplyr::mutate(points = round(sum(.data$points, na.rm = TRUE), 2)) %>%
    dplyr::ungroup() %>%
    tidyr::pivot_wider(
      id_cols = c("season", "week", "gsis_id", "sportradar_id", "sleeper_id", "player_name", "pos", "team", "points"),
      names_from = "metric",
      values_from = "value",
      values_fill = 0,
      values_fn = max
    )
}
christianlohr9 commented 1 year ago

And the last (and probably most annoying thing) is to update the usedata_statmapping.R which is not available for me^^

tanho63 commented 1 year ago

Hey Christian, thanks for the interest - I don't have bandwidth or plans to tackle this in the immediate future but perhaps can review it as an offseason thing.

The code above looks fine! I do not want to introduce a dependency on nflfastR in this package, so it would require the infrastructure legwork of getting this all sorted within the nflreadr structure in order to be able to do something like this.

pmadison commented 1 year ago

Hey @tanho63 - any chance you've got some cycles to check this out? Or @christianlohr9 maybe if @tanho63 can help direct us on the infra work we can tag team it?

tanho63 commented 1 year ago

Hiya! So I'd judge the steps required to implement as follows:

I haven't started on these yet, so happy to take some PRs in roughly this order!

TheMathNinja commented 1 year ago

Hey @tanho63, now that nflreadr::load_player_stats() has a defense option, would it be easy-ish to extend ffscrapr::ff_scoringhistory() to work with these?

tanho63 commented 1 year ago

Not something that I have bandwidth for in the near future, but would welcome a PR if someone wanted to tackle it