Add defense league points to ff_scoringhistory with new nflfastR defense player stats
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
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)
}
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
)
}
And the last (and probably most annoying thing) is to update the usedata_statmapping.R which is not available for me^^
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.
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?
Hiya! So I'd judge the steps required to implement as follows:
- [x] fix this bug in the nflfastR defense summarize function: nflverse/nflfastR#410 - probably by adding/binding the defense data to an empty dataframe so that it always has the columns in question
- [x] add a script to nflverse-pbp to build the data and upload to nflverse-data repo, something like https://github.com/nflverse/nflverse-pbp/blob/master/R/update_player_stats.R
- [x] update
nflreadr::load_player_stats()to read the new uploaded data https://github.com/nflverse/nflreadr/blob/main/R/load_player_stats.R - [ ] then extend
ffscrapr::ff_scoringhistory()to work with the defensive scoring, similar to what Christian posted above.
I haven't started on these yet, so happy to take some PRs in roughly this order!
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?
Not something that I have bandwidth for in the near future, but would welcome a PR if someone wanted to tackle it