I want your feedback to make the book better for you and other readers. If you find typos, errors, or places where the text may be improved, please let me know. The best ways to provide feedback are by GitHub or hypothes.is annotations.
You can leave a comment at the bottom of the page/chapter, or open an issue or submit a pull request on GitHub: https://github.com/isaactpetersen/Fantasy-Football-Analytics-Textbook
Alternatively, you can leave an annotation using hypothes.is.
To add an annotation, select some text and then click the
symbol on the pop-up menu.
To see the annotations of others, click the
symbol in the upper right-hand corner of the page.
18 Mythbusters: Putting Fantasy Football Beliefs/Anecdotes to the Test
18.1 Getting Started
18.1.1 Load Packages
18.1.2 Specify Package Options
18.1.3 Load Data
We created the player_stats_weekly.RData
and player_stats_seasonal.RData
objects in Section 4.4.3.
18.2 Do Players Perform Better in their Contract Year?
Considerable speculation exists regarding whether players perform better in their last year of their contract (i.e., their “contract year”). Fantasy football talking heads and commentators frequently discuss the benefit of selecting players who are in their contract year, because it supposedly means that player has more motivation to perform well so they get a new contract and get paid more. To our knowledge, no peer-reviewed studies have examined this question for football players. One study found that National Basketball Association (NBA) players improved in field goal percentage, points, and player efficiency rating (but not other statistics: rebounds, assists, steals, or blocks) from their pre-contract year to their contract year, and that Major League Baseball (MLB) players improved in runs batted in (RBIs; but not other statistics: batting average, slugging percentage, on base percentage, home runs, fielding percentage) from their pre-contract year to their contract year (White & Sheldon, 2014). Other casual analyses have been examined contract-year performance of National Football League (NFL) players, including articles in 2012 [Bales (2012); archived here] and 2022 [Niles (2022); archived here].
Let’s examine the question empirically. In order to do that, we have to make some assumptions/constraints. In this example, we will make the following constraints:
- We will determine a player’s contract year programmatically based on the year the contract was signed. For instance, if a player signed a 3-year contract in 2015, their contract would expire in 2018, and thus their contract year would be 2017. Note: this is a coarse way of determining a player’s contract year because it could depend on when during the year the player’s contract is signed. If we were submitting this analysis as a paper to a scientific journal, it would be important to verify each player’s contract year.
- We will examine performance in all seasons since 2011, beginning when most data for player contracts are available.
- For maximum statistical power to detect an effect if a contract year effect exists, we will examine all seasons for a player (since 2011), not just their contract year and their pre-contract year.
- To ensure a more fair, apples-to-apples comparison of the games in which players played, we will examine per-game performance (except for yards per carry, which is based on \(\frac{\text{rushing yards}}{\text{carries}}\) from the entire season).
- We will examine regular season games only (no postseason).
- To ensure we do not make generalization about a player’s performance in a season from a small sample, the player has to play at least 5 games in a given season for that player–season combination to be included in analysis.
For analysis, the same player contributes multiple observations of performance (i.e., multiple seasons) due to the longitudinal nature of the data. Inclusion of multiple data points from the same player would violate the assumption of multiple regression that all observations are independent. Thus, we use mixed-effects models that allow nonindependent observations. In our mixed-effects models, we include a random intercept for each player, to allow our model to account for players’ differing level of performance. We examine two mixed-effects models for each outcome variable: one model that accounts for the effects of age and experience, and one model that does not.
The model that does not account for the effects of age and experience includes:
- random intercepts to allow the model to estimate a different starting point for each player
- a fixed effect for whether the player is in a contract year
The model that accounts for the effects of age and experience includes:
- random intercepts to allow the model to estimate a different starting point for each player
- random linear slopes (i.e., random effect of linear age) to allow the model to estimate a different form of change for each player
- a fixed quadratic effect of age to allow for curvilinear effects
- a fixed effect of experience
- a fixed effect for whether the player is in a contract year
Code
# Subset to remove players without a year signed
nfl_playerContracts_subset <- nfl_playerContracts %>%
dplyr::filter(!is.na(year_signed) & year_signed != 0)
# Determine the contract year for a given contract
nfl_playerContracts_subset$contractYear <- nfl_playerContracts_subset$year_signed + nfl_playerContracts_subset$years - 1
# Arrange contracts by player and year_signed
nfl_playerContracts_subset <- nfl_playerContracts_subset %>%
dplyr::group_by(player, position) %>%
dplyr::arrange(player, position, -year_signed) %>%
dplyr::ungroup()
# Determine if the player played in the original contract year
nfl_playerContracts_subset <- nfl_playerContracts_subset %>%
dplyr::group_by(player, position) %>%
dplyr::mutate(
next_contract_start = lag(year_signed)) %>%
dplyr::ungroup() %>%
dplyr::mutate(
played_in_contract_year = ifelse(
is.na(next_contract_start) | contractYear < next_contract_start,
TRUE,
FALSE))
# Check individual players
#nfl_playerContracts_subset %>%
# dplyr::filter(player == "Aaron Rodgers") %>%
# dplyr::select(player:years, contractYear, next_contract_start, played_in_contract_year)
#
#nfl_playerContracts_subset %>%
# dplyr::filter(player %in% c("Jared Allen", "Aaron Rodgers")) %>%
# dplyr::select(player:years, contractYear, next_contract_start, played_in_contract_year)
# Subset data
nfl_playerContractYears <- nfl_playerContracts_subset %>%
dplyr::filter(played_in_contract_year == TRUE) %>%
dplyr::filter(position %in% c("QB","RB","WR","TE")) %>%
dplyr::select(player, position, team, contractYear) %>%
dplyr::mutate(merge_name = nflreadr::clean_player_names(player, lowercase = TRUE)) %>%
dplyr::rename(season = contractYear) %>%
dplyr::mutate(contractYear = 1)
# Merge with weekly and seasonal stats data
player_stats_weekly_offense <- player_stats_weekly %>%
dplyr::filter(position_group %in% c("QB","RB","WR","TE")) %>%
dplyr::mutate(merge_name = nflreadr::clean_player_names(player_display_name, lowercase = TRUE))
#nfl_actualStats_offense_seasonal <- nfl_actualStats_offense_seasonal %>%
# mutate(merge_name = nflreadr::clean_player_names(player_display_name, lowercase = TRUE))
player_statsContracts_offense_weekly <- dplyr::full_join(
player_stats_weekly_offense,
nfl_playerContractYears,
by = c("merge_name", "position_group" = "position", "season")
) %>%
dplyr::filter(position_group %in% c("QB","RB","WR","TE"))
#player_statsContracts_offense_seasonal <- full_join(
# player_stats_seasonal_offense,
# nfl_playerContractYears,
# by = c("merge_name", "position_group" = "position", "season")
#) %>%
# filter(position_group %in% c("QB","RB","WR","TE"))
player_statsContracts_offense_weekly$contractYear[which(is.na(player_statsContracts_offense_weekly$contractYear))] <- 0
#player_statsContracts_offense_seasonal$contractYear[which(is.na(player_statsContracts_offense_seasonal$contractYear))] <- 0
#player_statsContracts_offense_weekly$contractYear <- factor(
# player_statsContracts_offense_weekly$contractYear,
# levels = c(0, 1),
# labels = c("no", "yes"))
#player_statsContracts_offense_seasonal$contractYear <- factor(
# player_statsContracts_offense_seasonal$contractYear,
# levels = c(0, 1),
# labels = c("no", "yes"))
player_statsContracts_offense_weekly <- player_statsContracts_offense_weekly %>%
dplyr::arrange(merge_name, season, season_type, week)
#player_statsContracts_offense_seasonal <- player_statsContracts_offense_seasonal %>%
# arrange(merge_name, season)
player_statsContractsSubset_offense_weekly <- player_statsContracts_offense_weekly %>%
dplyr::filter(season_type == "REG")
#table(nfl_playerContracts$year_signed) # most contract data is available beginning in 2011
# Calculate Per Game Totals
player_statsContracts_seasonal <- player_statsContractsSubset_offense_weekly %>%
dplyr::group_by(player_id, season) %>%
dplyr::summarise(
player_display_name = petersenlab::Mode(player_display_name),
position_group = petersenlab::Mode(position_group),
age = min(age, na.rm = TRUE),
years_of_experience = min(years_of_experience, na.rm = TRUE),
rushing_yards = sum(rushing_yards, na.rm = TRUE), # season total
carries = sum(carries, na.rm = TRUE), # season total
rushing_epa = mean(rushing_epa, na.rm = TRUE),
receiving_yards = mean(receiving_yards, na.rm = TRUE),
receiving_epa = mean(receiving_epa, na.rm = TRUE),
fantasyPoints = sum(fantasyPoints, na.rm = TRUE), # season total
contractYear = mean(contractYear, na.rm = TRUE),
games = n(),
.groups = "drop_last"
) %>%
dplyr::mutate(
player_id = as.factor(player_id),
ypc = rushing_yards / carries,
contractYear = factor(
contractYear,
levels = c(0, 1),
labels = c("no", "yes")
))
player_statsContracts_seasonal[sapply(player_statsContracts_seasonal, is.infinite)] <- NA
player_statsContracts_seasonal$ageCentered20 <- player_statsContracts_seasonal$age - 20
player_statsContracts_seasonal$ageCentered20Quadratic <- player_statsContracts_seasonal$ageCentered20 ^ 2
# Merge with seasonal fantasy points data
18.2.1 QB
First, we prepare the data by merging and performing additional processing:
Code
# Merge with QBR data
nfl_espnQBR_weekly$merge_name <- paste(nfl_espnQBR_weekly$name_first, nfl_espnQBR_weekly$name_last, sep = " ") %>%
nflreadr::clean_player_names(., lowercase = TRUE)
nfl_contractYearQBR_weekly <- nfl_playerContractYears %>%
dplyr::filter(position == "QB") %>%
dplyr::full_join(
.,
nfl_espnQBR_weekly,
by = c("merge_name","team","season")
)
nfl_contractYearQBR_weekly$contractYear[which(is.na(nfl_contractYearQBR_weekly$contractYear))] <- 0
#nfl_contractYearQBR_weekly$contractYear <- factor(
# nfl_contractYearQBR_weekly$contractYear,
# levels = c(0, 1),
# labels = c("no", "yes"))
nfl_contractYearQBR_weekly <- nfl_contractYearQBR_weekly %>%
dplyr::arrange(merge_name, season, season_type, game_week)
nfl_contractYearQBRsubset_weekly <- nfl_contractYearQBR_weekly %>%
dplyr::filter(season_type == "Regular") %>%
dplyr::arrange(merge_name, season, season_type, game_week) %>%
mutate(
player = coalesce(player, name_display),
position = "QB") %>%
group_by(merge_name, player_id) %>%
fill(player, .direction = "downup")
# Merge with age and experience
nfl_contractYearQBRsubset_weekly <- player_statsContractsSubset_offense_weekly %>%
dplyr::filter(position == "QB") %>%
dplyr::select(merge_name, season, week, age, years_of_experience, fantasyPoints) %>%
full_join(
nfl_contractYearQBRsubset_weekly,
by = c("merge_name","season", c("week" = "game_week"))
) %>% select(player_id, season, week, player, everything()) %>%
arrange(player_id, season, week)
#hist(nfl_contractYearQBRsubset_weekly$qb_plays) # players have at least 20 dropbacks per game
# Calculate Per Game Totals
nfl_contractYearQBR_seasonal <- nfl_contractYearQBRsubset_weekly %>%
dplyr::group_by(merge_name, season) %>%
dplyr::summarise(
age = min(age, na.rm = TRUE),
years_of_experience = min(years_of_experience, na.rm = TRUE),
qbr = mean(qbr_total, na.rm = TRUE),
pts_added = mean(pts_added, na.rm = TRUE),
epa_pass = mean(pass, na.rm = TRUE),
qb_plays = sum(qb_plays, na.rm = TRUE), # season total
fantasyPoints = sum(fantasyPoints, na.rm = TRUE), # season total
contractYear = mean(contractYear, na.rm = TRUE),
games = n(),
.groups = "drop_last"
) %>%
dplyr::mutate(
contractYear = factor(
contractYear,
levels = c(0, 1),
labels = c("no", "yes")
))
nfl_contractYearQBR_seasonal[sapply(nfl_contractYearQBR_seasonal, is.infinite)] <- NA
nfl_contractYearQBR_seasonal$ageCentered20 <- nfl_contractYearQBR_seasonal$age - 20
nfl_contractYearQBR_seasonal$ageCentered20Quadratic <- nfl_contractYearQBR_seasonal$ageCentered20 ^ 2
nfl_contractYearQBR_seasonal <- nfl_contractYearQBR_seasonal %>%
group_by(merge_name) %>%
mutate(player_id = as.factor(as.character(cur_group_id())))
nfl_contractYearQBRsubset_seasonal <- nfl_contractYearQBR_seasonal %>%
dplyr::filter(
games >= 5, # keep only player-season combinations in which QBs played at least 5 games
season >= 2011) # keep only seasons since 2011 (when most contract data are available)
Then, we analyze the data. Below is a mixed model that examines whether a player has a higher QBR per game when they are in a contract year compared to when they are not in a contract year.
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: qbr ~ contractYear + (1 | player_id)
Data: nfl_contractYearQBR_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 9440.1
Scaled residuals:
Min 1Q Median 3Q Max
-3.2458 -0.5402 0.0769 0.5701 3.2401
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 110.5 10.51
Residual 199.0 14.11
Number of obs: 1127, groups: player_id, 262
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 44.6138 0.8532 237.9610 52.290 <2e-16 ***
contractYearyes -0.1586 1.1569 1010.8162 -0.137 0.891
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.242
R2m R2c
[1,] 1.272846e-05 0.3571013
contractYear emmean SE df lower.CL upper.CL
no 44.6 0.854 273 42.9 46.3
yes 44.5 1.260 769 42.0 46.9
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: qbr ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 + ageCentered20 | player_id)
Data: nfl_contractYearQBR_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 9367.1
Scaled residuals:
Min 1Q Median 3Q Max
-3.3664 -0.5127 0.0841 0.5489 3.2657
Random effects:
Groups Name Variance Std.Dev. Corr
player_id (Intercept) 126.9074 11.2653
ageCentered20 0.3854 0.6208 -0.32
Residual 191.2280 13.8285
Number of obs: 1119, groups: player_id, 258
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 3.941e+01 2.259e+00 1.940e+02 17.445 < 2e-16 ***
contractYearyes 8.814e-03 1.197e+00 1.005e+03 0.007 0.99413
ageCentered20 1.530e+00 6.493e-01 2.886e+02 2.357 0.01911 *
ageCentered20Quadratic -7.464e-02 2.254e-02 1.060e+02 -3.311 0.00127 **
years_of_experience -1.954e-01 5.397e-01 3.237e+02 -0.362 0.71748
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.060
ageCentrd20 -0.790 -0.075
agCntrd20Qd 0.736 0.053 -0.616
yrs_f_xprnc 0.238 -0.020 -0.693 -0.094
R2m R2c
[1,] 0.01244643 0.4032188
contractYear emmean SE df lower.CL upper.CL
no 44.2 0.905 251 42.5 46.0
yes 44.2 1.290 713 41.7 46.8
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: pts_added ~ contractYear + (1 | player_id)
Data: nfl_contractYearQBR_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 5132.9
Scaled residuals:
Min 1Q Median 3Q Max
-4.7318 -0.4972 0.0857 0.5439 4.2752
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 2.574 1.604
Residual 4.276 2.068
Number of obs: 1127, groups: player_id, 262
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) -0.7982 0.1283 224.1668 -6.222 2.38e-09 ***
contractYearyes -0.1155 0.1700 995.5919 -0.679 0.497
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.236
R2m R2c
[1,] 0.0003049317 0.3759501
contractYear emmean SE df lower.CL upper.CL
no -0.798 0.128 273 -1.05 -0.545
yes -0.914 0.187 758 -1.28 -0.546
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: pts_added ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 + ageCentered20 | player_id)
Data: nfl_contractYearQBR_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 5103.5
Scaled residuals:
Min 1Q Median 3Q Max
-4.8880 -0.4961 0.0894 0.5303 4.2769
Random effects:
Groups Name Variance Std.Dev. Corr
player_id (Intercept) 3.57351 1.8904
ageCentered20 0.01127 0.1061 -0.52
Residual 4.09939 2.0247
Number of obs: 1119, groups: player_id, 258
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) -1.580138 0.343810 185.033479 -4.596 7.96e-06 ***
contractYearyes -0.104459 0.175743 988.551064 -0.594 0.55239
ageCentered20 0.198359 0.097581 286.002874 2.033 0.04300 *
ageCentered20Quadratic -0.010753 0.003375 106.612781 -3.186 0.00189 **
years_of_experience 0.009459 0.080374 306.565256 0.118 0.90639
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.061
ageCentrd20 -0.790 -0.076
agCntrd20Qd 0.731 0.058 -0.624
yrs_f_xprnc 0.244 -0.020 -0.696 -0.081
R2m R2c
[1,] 0.01003626 0.415973
contractYear emmean SE df lower.CL upper.CL
no -0.823 0.134 254 -1.09 -0.558
yes -0.927 0.191 710 -1.30 -0.552
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: epa_pass ~ contractYear + (1 | player_id)
Data: nfl_contractYearQBR_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 4785.2
Scaled residuals:
Min 1Q Median 3Q Max
-3.0595 -0.5107 0.0386 0.5465 4.4071
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 2.508 1.584
Residual 2.981 1.727
Number of obs: 1127, groups: player_id, 262
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 1.1294 0.1198 243.0749 9.425 < 2e-16 ***
contractYearyes 0.3867 0.1433 979.1048 2.699 0.00707 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.211
R2m R2c
[1,] 0.00425061 0.4592752
contractYear emmean SE df lower.CL upper.CL
no 1.13 0.120 272 0.893 1.37
yes 1.52 0.166 704 1.189 1.84
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
mixedModelAge_epaPass <- lmerTest::lmer(
epa_pass ~ contractYear + ageCentered20 + ageCentered20Quadratic + years_of_experience + (1 | player_id), # removed random slopes to address convergence issue
data = nfl_contractYearQBR_seasonal,
control = lmerControl(optimizer = "bobyqa")
)
summary(mixedModelAge_epaPass)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: epa_pass ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 | player_id)
Data: nfl_contractYearQBR_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 4755.4
Scaled residuals:
Min 1Q Median 3Q Max
-3.2004 -0.4933 0.0484 0.5390 4.3305
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 2.559 1.600
Residual 2.934 1.713
Number of obs: 1119, groups: player_id, 258
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 3.313e-01 2.812e-01 9.569e+02 1.178 0.2390
contractYearyes 2.285e-01 1.485e-01 9.983e+02 1.539 0.1241
ageCentered20 1.372e-01 8.193e-02 7.395e+02 1.675 0.0944 .
ageCentered20Quadratic -4.517e-03 2.588e-03 1.057e+03 -1.746 0.0812 .
years_of_experience 1.785e-02 7.150e-02 4.128e+02 0.250 0.8030
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.067
ageCentrd20 -0.770 -0.072
agCntrd20Qd 0.704 0.057 -0.562
yrs_f_xprnc 0.279 -0.025 -0.737 -0.108
R2m R2c
[1,] 0.01876087 0.4759311
contractYear emmean SE df lower.CL upper.CL
no 1.21 0.123 271 0.966 1.45
yes 1.44 0.168 688 1.107 1.77
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: fantasyPoints ~ contractYear + (1 | player_id)
Data: nfl_contractYearQBR_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 13299.3
Scaled residuals:
Min 1Q Median 3Q Max
-3.7943 -0.5637 -0.0847 0.6323 2.7416
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 6286 79.29
Residual 5475 74.00
Number of obs: 1127, groups: player_id, 262
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 111.494 5.747 299.608 19.399 < 2e-16 ***
contractYearyes -29.946 6.188 990.937 -4.839 1.51e-06 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.188
R2m R2c
[1,] 0.0118063 0.5399733
contractYear emmean SE df lower.CL upper.CL
no 111.5 5.75 271 100.2 122.8
yes 81.5 7.62 646 66.6 96.5
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
mixedModelAge_fantasyPtsPass <- lmerTest::lmer(
fantasyPoints ~ contractYear + ageCentered20 + ageCentered20Quadratic + years_of_experience + (1 | player_id), # removed random slopes to address convergence issue
data = nfl_contractYearQBR_seasonal,
control = lmerControl(optimizer = "bobyqa")
)
summary(mixedModelAge_fantasyPtsPass)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula:
fantasyPoints ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 | player_id)
Data: nfl_contractYearQBR_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 13180.9
Scaled residuals:
Min 1Q Median 3Q Max
-3.9486 -0.5690 -0.0741 0.6231 2.6086
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 6564 81.02
Residual 5331 73.01
Number of obs: 1119, groups: player_id, 258
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 138.6743 12.6049 971.2085 11.002 < 2e-16 ***
contractYearyes -23.5326 6.3995 998.9610 -3.677 0.000248 ***
ageCentered20 -8.7711 3.7243 818.5205 -2.355 0.018752 *
ageCentered20Quadratic -0.0936 0.1121 1044.3790 -0.835 0.403818
years_of_experience 8.4189 3.3429 523.0562 2.518 0.012085 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.068
ageCentrd20 -0.754 -0.068
agCntrd20Qd 0.675 0.054 -0.526
yrs_f_xprnc 0.305 -0.024 -0.764 -0.111
R2m R2c
[1,] 0.03683421 0.5683428
contractYear emmean SE df lower.CL upper.CL
no 110.4 5.96 272 98.7 122
yes 86.9 7.73 623 71.7 102
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
18.2.2 RB
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: ypc ~ contractYear + (1 | player_id)
Data: player_statsContractsRB_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 6361.6
Scaled residuals:
Min 1Q Median 3Q Max
-7.9753 -0.3998 0.0048 0.4031 14.8057
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 0.5088 0.7133
Residual 1.8716 1.3681
Number of obs: 1744, groups: player_id, 531
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 3.914e+00 5.134e-02 5.083e+02 76.229 <2e-16 ***
contractYearyes 6.210e-03 8.163e-02 1.677e+03 0.076 0.939
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.373
R2m R2c
[1,] 3.13029e-06 0.2137492
contractYear emmean SE df lower.CL upper.CL
no 3.91 0.0514 631 3.81 4.01
yes 3.92 0.0787 1258 3.77 4.07
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: ypc ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 + ageCentered20 | player_id)
Data: player_statsContractsRB_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 6346.5
Scaled residuals:
Min 1Q Median 3Q Max
-7.7920 -0.3853 -0.0068 0.3840 14.2122
Random effects:
Groups Name Variance Std.Dev. Corr
player_id (Intercept) 0.39629 0.6295
ageCentered20 0.01044 0.1022 -0.28
Residual 1.79728 1.3406
Number of obs: 1742, groups: player_id, 529
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 4.222e+00 1.705e-01 7.175e+02 24.767 <2e-16 ***
contractYearyes 1.063e-01 8.808e-02 1.602e+03 1.207 0.228
ageCentered20 -5.096e-02 5.995e-02 8.152e+02 -0.850 0.396
ageCentered20Quadratic -2.844e-03 4.225e-03 4.258e+02 -0.673 0.501
years_of_experience 1.446e-02 3.780e-02 4.723e+02 0.382 0.702
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.150
ageCentrd20 -0.891 -0.172
agCntrd20Qd 0.795 0.126 -0.800
yrs_f_xprnc 0.057 -0.067 -0.355 -0.198
R2m R2c
[1,] 0.01710798 0.2675485
contractYear emmean SE df lower.CL upper.CL
no 3.87 0.0547 555 3.76 3.97
yes 3.97 0.0824 1231 3.81 4.13
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: rushing_epa ~ contractYear + (1 | player_id)
Data: player_statsContractsRB_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 5057.5
Scaled residuals:
Min 1Q Median 3Q Max
-4.5550 -0.5026 0.0814 0.5818 3.4230
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 0.09939 0.3153
Residual 0.97446 0.9871
Number of obs: 1744, groups: player_id, 531
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) -0.64471 0.03171 652.00671 -20.33 <2e-16 ***
contractYearyes 0.03333 0.05654 1741.98241 0.59 0.556
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.441
R2m R2c
[1,] 0.0001998691 0.09273524
contractYear emmean SE df lower.CL upper.CL
no -0.645 0.0317 650 -0.707 -0.582
yes -0.611 0.0513 1161 -0.712 -0.511
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: rushing_epa ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 + ageCentered20 | player_id)
Data: player_statsContractsRB_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 5062.4
Scaled residuals:
Min 1Q Median 3Q Max
-4.6144 -0.4961 0.0697 0.5833 3.4213
Random effects:
Groups Name Variance Std.Dev. Corr
player_id (Intercept) 0.172837 0.41574
ageCentered20 0.002041 0.04517 -0.67
Residual 0.958451 0.97901
Number of obs: 1742, groups: player_id, 529
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) -6.614e-01 1.179e-01 4.017e+02 -5.608 3.81e-08 ***
contractYearyes 6.785e-02 5.998e-02 1.544e+03 1.131 0.25816
ageCentered20 5.107e-02 3.973e-02 4.080e+02 1.286 0.19930
ageCentered20Quadratic -1.261e-03 2.753e-03 2.096e+02 -0.458 0.64726
years_of_experience -5.985e-02 2.252e-02 4.867e+02 -2.657 0.00814 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.148
ageCentrd20 -0.902 -0.196
agCntrd20Qd 0.818 0.153 -0.838
yrs_f_xprnc 0.030 -0.054 -0.307 -0.191
R2m R2c
[1,] 0.008101641 0.1113651
contractYear emmean SE df lower.CL upper.CL
no -0.657 0.0325 581 -0.721 -0.593
yes -0.589 0.0532 1158 -0.694 -0.485
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: fantasyPoints ~ contractYear + (1 | player_id)
Data: player_statsContractsRB_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 20808.1
Scaled residuals:
Min 1Q Median 3Q Max
-3.1381 -0.5051 -0.1721 0.4160 3.8976
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 3550 59.58
Residual 3039 55.13
Number of obs: 1844, groups: player_id, 548
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 81.576 3.056 654.334 26.69 < 2e-16 ***
contractYearyes -14.047 3.469 1590.032 -4.05 5.37e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.235
R2m R2c
[1,] 0.005650508 0.5413615
contractYear emmean SE df lower.CL upper.CL
no 81.6 3.06 597 75.6 87.6
yes 67.5 4.05 1247 59.6 75.5
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula:
fantasyPoints ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 + ageCentered20 | player_id)
Data: player_statsContractsRB_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 20671.1
Scaled residuals:
Min 1Q Median 3Q Max
-3.4383 -0.4918 -0.1585 0.4016 3.6466
Random effects:
Groups Name Variance Std.Dev. Corr
player_id (Intercept) 6826.30 82.621
ageCentered20 54.19 7.361 -0.75
Residual 2642.05 51.401
Number of obs: 1842, groups: player_id, 546
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 70.0164 8.8102 728.0439 7.947 7.26e-15 ***
contractYearyes -9.6185 3.6077 1566.8723 -2.666 0.00775 **
ageCentered20 1.5209 3.0252 967.0698 0.503 0.61527
ageCentered20Quadratic -1.1202 0.1821 511.8087 -6.151 1.56e-09 ***
years_of_experience 12.0523 2.0881 659.5743 5.772 1.21e-08 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.168
ageCentrd20 -0.868 -0.169
agCntrd20Qd 0.716 0.158 -0.740
yrs_f_xprnc 0.264 -0.065 -0.552 -0.086
R2m R2c
[1,] 0.06212416 0.6124686
contractYear emmean SE df lower.CL upper.CL
no 80.7 3.08 598 74.7 86.8
yes 71.1 4.04 1227 63.2 79.0
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
18.2.3 WR/TE
Code
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: receiving_yards ~ contractYear + (1 | player_id)
Data: player_statsContractsWRTE_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 32762.4
Scaled residuals:
Min 1Q Median 3Q Max
-4.8523 -0.5266 -0.1105 0.5070 4.5621
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 280.4 16.74
Residual 182.7 13.52
Number of obs: 3845, groups: player_id, 1087
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 25.1265 0.5907 1295.7691 42.53 < 2e-16 ***
contractYearyes -4.0877 0.5569 3257.3755 -7.34 2.69e-13 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.234
R2m R2c
[1,] 0.007389053 0.6084049
contractYear emmean SE df lower.CL upper.CL
no 25.1 0.591 1189 24.0 26.3
yes 21.0 0.711 2077 19.6 22.4
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
mixedModelAge_receivingYards <- lmerTest::lmer(
receiving_yards ~ contractYear + ageCentered20 + ageCentered20Quadratic + years_of_experience + (1 + ageCentered20 | player_id),
data = player_statsContractsWRTE_seasonal,
control = lmerControl(optimizer = "bobyqa")
)
summary(mixedModelAge_receivingYards)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula:
receiving_yards ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 + ageCentered20 | player_id)
Data: player_statsContractsWRTE_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 32324.3
Scaled residuals:
Min 1Q Median 3Q Max
-2.9762 -0.5207 -0.0957 0.4753 3.8095
Random effects:
Groups Name Variance Std.Dev. Corr
player_id (Intercept) 546.303 23.37
ageCentered20 5.809 2.41 -0.69
Residual 136.871 11.70
Number of obs: 3843, groups: player_id, 1086
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 14.67660 1.57189 1531.91283 9.337 < 2e-16 ***
contractYearyes -3.06203 0.54737 3034.32724 -5.594 2.42e-08 ***
ageCentered20 2.46053 0.53060 2230.72821 4.637 3.74e-06 ***
ageCentered20Quadratic -0.43117 0.02688 1514.70198 -16.041 < 2e-16 ***
years_of_experience 3.34048 0.40668 1329.57876 8.214 5.02e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.124
ageCentrd20 -0.844 -0.152
agCntrd20Qd 0.659 0.072 -0.648
yrs_f_xprnc 0.336 0.033 -0.663 -0.066
R2m R2c
[1,] 0.1116187 0.7445546
contractYear emmean SE df lower.CL upper.CL
no 24.0 0.622 1199 22.8 25.2
yes 20.9 0.713 1900 19.5 22.3
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: receiving_epa ~ contractYear + (1 | player_id)
Data: player_statsContractsWRTE_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 12590.8
Scaled residuals:
Min 1Q Median 3Q Max
-5.5737 -0.5713 -0.0390 0.5357 3.8971
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 0.555 0.745
Residual 1.302 1.141
Number of obs: 3770, groups: player_id, 1070
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 0.65807 0.03346 1439.73658 19.669 < 2e-16 ***
contractYearyes -0.15989 0.04531 3584.95730 -3.529 0.000422 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.357
R2m R2c
[1,] 0.002833608 0.300893
contractYear emmean SE df lower.CL upper.CL
no 0.658 0.0335 1267 0.592 0.724
yes 0.498 0.0457 2456 0.409 0.588
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula:
receiving_epa ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 + ageCentered20 | player_id)
Data: player_statsContractsWRTE_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 12574
Scaled residuals:
Min 1Q Median 3Q Max
-5.4222 -0.5657 -0.0320 0.5251 3.8600
Random effects:
Groups Name Variance Std.Dev. Corr
player_id (Intercept) 0.937883 0.9684
ageCentered20 0.005505 0.0742 -0.66
Residual 1.248330 1.1173
Number of obs: 3769, groups: player_id, 1069
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 3.515e-01 1.040e-01 1.118e+03 3.379 0.000753 ***
contractYearyes -1.599e-01 4.797e-02 3.492e+03 -3.333 0.000868 ***
ageCentered20 7.715e-02 3.397e-02 1.209e+03 2.271 0.023338 *
ageCentered20Quadratic -9.347e-03 1.880e-03 4.735e+02 -4.972 9.29e-07 ***
years_of_experience 6.136e-02 2.302e-02 1.144e+03 2.665 0.007799 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.145
ageCentrd20 -0.871 -0.206
agCntrd20Qd 0.758 0.119 -0.742
yrs_f_xprnc 0.203 0.044 -0.524 -0.121
R2m R2c
[1,] 0.01276357 0.3377774
contractYear emmean SE df lower.CL upper.CL
no 0.656 0.0346 1214 0.588 0.724
yes 0.496 0.0468 2502 0.404 0.588
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: fantasyPoints ~ contractYear + (1 | player_id)
Data: player_statsContractsWRTE_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 42563.2
Scaled residuals:
Min 1Q Median 3Q Max
-3.2497 -0.5267 -0.1437 0.4778 4.5954
Random effects:
Groups Name Variance Std.Dev.
player_id (Intercept) 2935 54.18
Residual 2473 49.73
Number of obs: 3845, groups: player_id, 1087
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 76.217 1.978 1333.859 38.533 < 2e-16 ***
contractYearyes -14.118 2.033 3340.343 -6.945 4.52e-12 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
contrctYrys -0.257
R2m R2c
[1,] 0.007544551 0.5461689
contractYear emmean SE df lower.CL upper.CL
no 76.2 1.98 1207 72.3 80.1
yes 62.1 2.44 2201 57.3 66.9
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
Code
mixedModelAge_fantasyPtsReceiving <- lmerTest::lmer(
fantasyPoints ~ contractYear + ageCentered20 + ageCentered20Quadratic + years_of_experience + (1 + ageCentered20 | player_id),
data = player_statsContractsWRTE_seasonal,
control = lmerControl(optimizer = "bobyqa")
)
summary(mixedModelAge_fantasyPtsReceiving)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula:
fantasyPoints ~ contractYear + ageCentered20 + ageCentered20Quadratic +
years_of_experience + (1 + ageCentered20 | player_id)
Data: player_statsContractsWRTE_seasonal
Control: lmerControl(optimizer = "bobyqa")
REML criterion at convergence: 42197
Scaled residuals:
Min 1Q Median 3Q Max
-3.0668 -0.4966 -0.1283 0.4563 4.9583
Random effects:
Groups Name Variance Std.Dev. Corr
player_id (Intercept) 5865.96 76.590
ageCentered20 60.78 7.796 -0.71
Residual 1960.23 44.275
Number of obs: 3843, groups: player_id, 1086
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 43.3018 5.5012 1472.0304 7.871 6.75e-15 ***
contractYearyes -10.4200 2.0348 3167.5419 -5.121 3.22e-07 ***
ageCentered20 7.3181 1.8400 2151.2044 3.977 7.20e-05 ***
ageCentered20Quadratic -1.3780 0.0964 1291.7568 -14.294 < 2e-16 ***
years_of_experience 11.3259 1.3642 1283.5592 8.302 2.57e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr) cntrcY agCn20 agC20Q
contrctYrys 0.130
ageCentrd20 -0.852 -0.164
agCntrd20Qd 0.684 0.082 -0.675
yrs_f_xprnc 0.306 0.035 -0.629 -0.076
R2m R2c
[1,] 0.1033737 0.6793945
contractYear emmean SE df lower.CL upper.CL
no 72.5 2.07 1204 68.5 76.6
yes 62.1 2.45 2057 57.3 66.9
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
18.2.4 QB/RB/WR/TE
18.3 Conclusion
18.4 Session Info
R version 4.5.0 (2025-04-11)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 24.04.2 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
locale:
[1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
[4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
[7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
time zone: UTC
tzcode source: system (glibc)
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] lubridate_1.9.4 forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4
[5] purrr_1.0.4 readr_2.1.5 tidyr_1.3.1 tibble_3.2.1
[9] ggplot2_3.5.2 tidyverse_2.0.0 emmeans_1.11.0 MuMIn_1.48.11
[13] lmerTest_3.1-3 lme4_1.1-37 Matrix_1.7-3 nflreadr_1.4.1
[17] petersenlab_1.1.3
loaded via a namespace (and not attached):
[1] tidyselect_1.2.1 psych_2.5.3 viridisLite_0.4.2
[4] farver_2.1.2 fastmap_1.2.0 TH.data_1.1-3
[7] digest_0.6.37 rpart_4.1.24 timechange_0.3.0
[10] estimability_1.5.1 lifecycle_1.0.4 cluster_2.1.8.1
[13] survival_3.8-3 magrittr_2.0.3 compiler_4.5.0
[16] rlang_1.1.6 Hmisc_5.2-3 tools_4.5.0
[19] yaml_2.3.10 data.table_1.17.0 knitr_1.50
[22] htmlwidgets_1.6.4 mnormt_2.1.1 plyr_1.8.9
[25] RColorBrewer_1.1-3 multcomp_1.4-28 withr_3.0.2
[28] foreign_0.8-90 numDeriv_2016.8-1.1 nnet_7.3-20
[31] grid_4.5.0 stats4_4.5.0 lavaan_0.6-19
[34] xtable_1.8-4 colorspace_2.1-1 scales_1.4.0
[37] MASS_7.3-65 cli_3.6.5 mvtnorm_1.3-3
[40] rmarkdown_2.29 reformulas_0.4.0 generics_0.1.3
[43] rstudioapi_0.17.1 tzdb_0.5.0 reshape2_1.4.4
[46] minqa_1.2.8 DBI_1.2.3 cachem_1.1.0
[49] splines_4.5.0 parallel_4.5.0 base64enc_0.1-3
[52] mitools_2.4 vctrs_0.6.5 sandwich_3.1-1
[55] boot_1.3-31 jsonlite_2.0.0 hms_1.1.3
[58] pbkrtest_0.5.3 Formula_1.2-5 htmlTable_2.4.3
[61] glue_1.8.0 nloptr_2.2.1 codetools_0.2-20
[64] stringi_1.8.7 gtable_0.3.6 quadprog_1.5-8
[67] pillar_1.10.2 htmltools_0.5.8.1 R6_2.6.1
[70] Rdpack_2.6.4 mix_1.0-13 evaluate_1.0.3
[73] pbivnorm_0.6.0 lattice_0.22-6 rbibutils_2.3
[76] backports_1.5.0 broom_1.0.8 memoise_2.0.1
[79] Rcpp_1.0.14 coda_0.19-4.1 gridExtra_2.3
[82] nlme_3.1-168 checkmate_2.3.2 xfun_0.52
[85] zoo_1.8-14 pkgconfig_2.0.3