This tutorial investigates whether a strong first quarter is associated with winning an AFL match. Using 2023 AFL match data, I will calculate quarter-time scores, compare match outcomes, and use logistic regression to investigate the relationship.
First, load the tidyverse package and import the CSV file. Make sure the CSV file is saved in your Team_A folder.
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.3
## Warning: package 'ggplot2' was built under R version 4.5.3
## Warning: package 'tibble' was built under R version 4.5.3
## Warning: package 'tidyr' was built under R version 4.5.3
## Warning: package 'readr' was built under R version 4.5.3
## Warning: package 'purrr' was built under R version 4.5.3
## Warning: package 'dplyr' was built under R version 4.5.3
## Warning: package 'stringr' was built under R version 4.5.3
## Warning: package 'forcats' was built under R version 4.5.3
## Warning: package 'lubridate' was built under R version 4.5.3
afl <- read_csv("matches_2023 AFL.csv")
head(afl)
## # A tibble: 6 × 22
## round_num venue date year team_1_team_name team_1_q1_goals
## <chr> <chr> <dttm> <dbl> <chr> <dbl>
## 1 1 M.C.G. 2023-03-16 19:20:00 2023 Richmond 1
## 2 1 M.C.G. 2023-03-17 19:40:00 2023 Geelong 6
## 3 1 Docklands 2023-03-18 13:45:00 2023 North Melbourne 3
## 4 1 Adelaide… 2023-03-18 16:05:00 2023 Port Adelaide 3
## 5 1 M.C.G. 2023-03-18 19:25:00 2023 Melbourne 3
## 6 1 Carrara 2023-03-18 19:00:00 2023 Gold Coast 2
## # ℹ 16 more variables: team_1_q1_behinds <dbl>, team_1_q2_goals <dbl>,
## # team_1_q2_behinds <dbl>, team_1_q3_goals <dbl>, team_1_q3_behinds <dbl>,
## # team_1_final_goals <dbl>, team_1_final_behinds <dbl>,
## # team_2_team_name <chr>, team_2_q1_goals <dbl>, team_2_q1_behinds <dbl>,
## # team_2_q2_goals <dbl>, team_2_q2_behinds <dbl>, team_2_q3_goals <dbl>,
## # team_2_q3_behinds <dbl>, team_2_final_goals <dbl>,
## # team_2_final_behinds <dbl>
In Australian rules football, a goal is worth six points and a behind is worth one point.
afl <- afl %>%
mutate(
team1_q1_points =
team_1_q1_goals * 6 + team_1_q1_behinds,
team2_q1_points =
team_2_q1_goals * 6 + team_2_q1_behinds,
team1_final_points =
team_1_final_goals * 6 + team_1_final_behinds,
team2_final_points =
team_2_final_goals * 6 + team_2_final_behinds,
q1_margin = team1_q1_points - team2_q1_points,
final_margin = team1_final_points - team2_final_points
)
Team 1 is recorded as the winner when its final score is higher. Draws are excluded from the logistic regression.
afl <- afl %>%
mutate(
team1_win = case_when(
final_margin > 0 ~ 1,
final_margin < 0 ~ 0,
TRUE ~ NA_real_
)
)
afl_model <- afl %>%
filter(!is.na(team1_win))
afl_model %>%
mutate(
q1_status = case_when(
q1_margin > 0 ~ "Leading",
q1_margin < 0 ~ "Trailing",
TRUE ~ "Level"
)
) %>%
group_by(q1_status) %>%
summarise(
matches = n(),
win_rate = mean(team1_win),
.groups = "drop"
)
## # A tibble: 3 × 3
## q1_status matches win_rate
## <chr> <int> <dbl>
## 1 Leading 117 0.718
## 2 Level 3 0.667
## 3 Trailing 94 0.404
The win rate represents the proportion of matches won by Team 1 within each first-quarter group.
ggplot(afl_model, aes(x = q1_margin, y = team1_win)) +
geom_jitter(height = 0.05, width = 0, alpha = 0.5) +
labs(
title = "First-Quarter Margin and AFL Match Results",
x = "Team 1's first-quarter points margin",
y = "Team 1 won (1 = yes, 0 = no)"
) +
theme_minimal()
Logistic regression estimates the relationship between the first-quarter points margin and the probability of winning.
model <- glm(
team1_win ~ q1_margin,
data = afl_model,
family = binomial
)
summary(model)
##
## Call:
## glm(formula = team1_win ~ q1_margin, family = binomial, data = afl_model)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 0.23782 0.15271 1.557 0.119
## q1_margin 0.06232 0.01127 5.528 3.23e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 291.24 on 213 degrees of freedom
## Residual deviance: 249.93 on 212 degrees of freedom
## AIC: 253.93
##
## Number of Fisher Scoring iterations: 4
exp(coef(model))
## (Intercept) q1_margin
## 1.268475 1.064302
The odds ratio for the first-quarter margin indicates how the odds of winning change with each additional point in the first-quarter margin.
new_margins <- tibble(
q1_margin = seq(-30, 30, by = 5)
)
new_margins$predicted_probability <- predict(
model,
newdata = new_margins,
type = "response"
)
new_margins
## # A tibble: 13 × 2
## q1_margin predicted_probability
## <dbl> <dbl>
## 1 -30 0.164
## 2 -25 0.211
## 3 -20 0.267
## 4 -15 0.332
## 5 -10 0.405
## 6 -5 0.482
## 7 0 0.559
## 8 5 0.634
## 9 10 0.703
## 10 15 0.764
## 11 20 0.815
## 12 25 0.858
## 13 30 0.892
ggplot(
new_margins,
aes(x = q1_margin, y = predicted_probability)
) +
geom_line() +
labs(
title = "Predicted Probability of Winning",
x = "First-quarter points margin",
y = "Predicted probability of Team 1 winning"
) +
theme_minimal()
In this dataset, Team 1 won approximately 71.8% of non-drawn matches when leading at quarter time, compared with 40.4% when trailing.
The logistic regression coefficient for first-quarter margin was positive, indicating that a larger first-quarter lead was associated with higher odds of winning.
This analysis identifies an association, not proof that a strong first quarter causes a team to win. It uses one season of match data and only one predictor. Other factors, including team strength and match conditions, may also influence the final result.
The findings suggest that first-quarter performance is useful for understanding match outcomes, but it cannot explain every win or loss.