9.10 Simulate Season

set.seed(20250611)
schedule_talent <- schedule_talent |>
  mutate(
    outcome = rbinom(nrow(schedule_talent), 1, prob_home),
    winner = if_else(outcome == 1, Home, Visitor)
)
Detroit Tigers 1968 Schedule
sample of 10 games
lgID Home Visitor talent_home talent_visitor prob_home outcome winner
AL BAL DET −0.10 0.35 0.39 0 DET
AL DET NYA 0.35 −0.02 0.59 1 DET
AL DET MIN 0.35 −0.15 0.62 1 DET
AL CLE DET 0.26 0.35 0.48 1 CLE
AL NYA DET −0.02 0.35 0.41 0 DET
AL BAL DET −0.10 0.35 0.39 0 DET
AL NYA DET −0.02 0.35 0.41 1 NYA
AL CLE DET 0.26 0.35 0.48 1 CLE
AL BOS DET −0.24 0.35 0.36 0 DET
AL DET BAL 0.35 −0.10 0.61 0 BAL
table code
set.seed(20250611)
schedule_talent |>
  filter(Home == "DET" | Visitor == "DET") |>
  slice_sample(n = 10) |>
  gt() |>
  cols_align(align = "center") |>
  fmt_number(columns = c(talent_home, talent_visitor, prob_home),
             decimals = 2) |>
  tab_header(title = "Detroit Tigers 1968 Schedule",
             subtitle = "sample of 10 games") |>
  tab_style(
    locations = cells_body(columns = c(Home, prob_home), rows = Home == "DET" ),
    style = list(cell_fill(color = "#FA4616"), cell_text(color = "#0C2340"))) |>
  tab_style(
    locations = cells_body(columns = Visitor, rows = Visitor == "DET" ),
    style = list(cell_fill(color = "#FA4616"), cell_text(color = "#0C2340"))) |>
  tab_style(
    locations = cells_body(columns = c(Home, prob_home), rows = Home != "DET" ),
    style = list(cell_fill(color = "#0C2340"), cell_text(color = "#FA4616"))) |>
  tab_style(
    locations = cells_body(columns = Visitor, rows = Visitor != "DET" ),
    style = list(cell_fill(color = "#0C2340"), cell_text(color = "#FA4616")))
results <- schedule_talent |> 
  group_by(winner) |>
  summarize(Wins = n()) |>
  inner_join(teams_68, by = c("winner" = "teamID"))

9.10.1 Standings

win_league <- function(res) {
  set.seed(20250611)
  res |>
    group_by(lgID) |>
    mutate(
      tiebreaker = runif(n = length(talent)),
      wins_total = Wins + tiebreaker,
      rank = min_rank(desc(wins_total)),
      is_winner_lg = wins_total == max(wins_total)
    )
}
sim_1968 <- win_league(results) |>
  rename(team = winner)
1968 Season Standings
via simulation
team Wins talent tiebreaker wins_total rank is_winner_lg
AL
DET 98 0.35 0.78 98.78 1 TRUE
CHA 97 0.07 0.85 97.85 2 FALSE
CLE 95 0.26 0.19 95.19 3 FALSE
NYA 86 −0.02 0.58 86.58 4 FALSE
MIN 80 −0.15 0.65 80.65 5 FALSE
OAK 74 −0.14 0.90 74.90 6 FALSE
WS2 74 −0.02 0.75 74.75 7 FALSE
BAL 74 −0.10 0.31 74.31 8 FALSE
CAL 71 −0.17 0.12 71.12 9 FALSE
BOS 61 −0.24 0.05 61.05 10 FALSE
NL
SLN 99 0.31 0.67 99.67 1 TRUE
HOU 99 0.19 0.45 99.45 2 FALSE
CIN 95 0.18 0.23 95.23 3 FALSE
CHN 85 0.03 0.54 85.54 4 FALSE
SFN 85 −0.01 0.46 85.46 5 FALSE
ATL 78 −0.05 0.46 78.46 6 FALSE
NYN 73 −0.18 0.28 73.28 7 FALSE
PHI 67 −0.32 0.24 67.24 8 FALSE
LAN 65 −0.08 0.47 65.47 9 FALSE
PIT 64 −0.08 0.48 64.48 10 FALSE
table code
sim_1968 |>
  arrange(rank) |>
  gt() |>
  cols_align(align = "center") |>
  data_color(columns = Wins,
             palette = "inferno") |>
  fmt_number(columns = c(talent, tiebreaker, wins_total),
             decimals = 2) |>
  tab_header(title = "1968 Season Standings",
             subtitle = "via simulation")

9.10.2 Simulate World Series

set.seed(20250611)
ws_winner <- sim_1968 |>
  filter(is_winner_lg) |>
  ungroup() |>
  mutate(
    outcome = as.numeric(rmultinom(1, 7, exp(talent))),
    is_winner_ws = outcome > 3
  )
1968 Post-Season
via simulation
team Wins lgID talent outcome is_winner_ws
DET 98 AL 0.35 4 TRUE
SLN 99 NL 0.31 3 FALSE
table code
ws_winner |>
  select(team, Wins, lgID, talent, outcome, is_winner_ws) |>
  gt() |>
  cols_align(align = "center") |>
  fmt_number(columns = talent,
             decimals = 2) |>
  tab_header(title = "1968 Post-Season",
             subtitle = "via simulation") |>
  tab_style(
    locations = cells_body(columns = c(team, outcome, is_winner_ws), 
                           rows = team == "DET" ),
    style = list(cell_fill(color = "#FA4616"), cell_text(color = "#0C2340"))) |>
  tab_style(
    locations = cells_body(columns = c(team, outcome, is_winner_ws), 
                           rows = team == "SLN" ),
    style = list(cell_fill(color = "#C41E3A"), cell_text(color = "#0C2340"))) |>
  tab_style(locations = cells_body(columns = outcome),
            style = cell_text(weight = "bold"))