Created
May 4, 2026 22:08
-
-
Save cavedave/f2489c6b93ca6bab88a5be05d2b385ed to your computer and use it in GitHub Desktop.
World Snooker Crucible: ggplot figures from snooker.org century data (R + CSV)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Year | Centuries | High | Break_Makers | |
|---|---|---|---|---|
| 2026 | 81 | |||
| 2025 | 107 | 147 | Mark Allen | |
| 2024 | 63 | 142 | Jackson Page, Mark J Williams and Ricky Walden | |
| 2023 | 90 | 147 | Kyren Wilson and Mark Selby | |
| 2022 | 109 | 147 | Neil Robertson | |
| 2021 | 108 | 144 | Shaun Murphy | |
| 2020 | 79 | 147 | John Higgins | |
| 2019 | 100 | 143 | John Higgins | |
| 2018 | 84 | 146 | John Higgins | |
| 2017 | 74 | 146 | Ronnie O'Sullivan | |
| 2016 | 86 | 143 | Kyren Wilson | |
| 2015 | 86 | 145 | Neil Robertson and Stuart Bingham | |
| 2014 | 58 | 140 | Neil Robertson | |
| 2013 | 55 | 143 | Neil Robertson | |
| 2012 | 71 | 147 | Stephen Hendry | |
| 2011 | 74 | 138 | Mark King and Ding Junhui | |
| 2010 | 60 | 146 | Mark Allen and Graeme Dott | |
| 2009 | 83 | 147 | Stephen Hendry | |
| 2008 | 62 | 147 | Ronnie O'Sullivan and Allister Carter | |
| 2007 | 68 | 144 | Allister Carter | |
| 2006 | 46 | 140 | Ronnie O'Sullivan | |
| 2005 | 63 | 147 | Mark J Williams | |
| 2004 | 55 | 145 | Joe Perry | |
| 2003 | 53 | 147 | Ronnie O'Sullivan | |
| 2002 | 68 | 145 | Matthew Stevens | |
| 2001 | 53 | 140 | Joe Swail | |
| 2000 | 54 | 143 | Matthew Stevens | |
| 1999 | 53 | 142 | John Higgins | |
| 1998 | 59 | 143 | John Higgins and Jimmy White | |
| 1997 | 39 | 147 | Ronnie O'Sullivan | |
| 1996 | 48 | 144 | Tony Drago and Peter Ebdon | |
| 1995 | 30 | 147 | Stephen Hendry | |
| 1994 | 35 | 143 | Alan McManus | |
| 1993 | 35 | 144 | Steve Davis | |
| 1992 | 25 | 147 | Jimmy White | |
| 1991 | 31 | 140 | Jimmy White | |
| 1990 | 18 | 140 | John Parrott | |
| 1989 | 19 | 141 | Stephen Hendry | |
| 1988 | 18 | 140 | Steve James | |
| 1987 | 18 | 127 | Steve Davis | |
| 1986 | 20 | 134 | Steve Davis | |
| 1985 | 14 | 143 | Bill Werbeniuk | |
| 1984 | 8 | 138 | Rex Williams | |
| 1983 | 18 | 147 | Cliff Thorburn | |
| 1982 | 10 | 143 | Willie Thorne | |
| 1981 | 13 | 145 | Doug Mountjoy | |
| 1980 | 11 | 136 | Steve Davis and Kirk Stevens | |
| 1979 | 13 | 142 | Bill Werbeniuk | |
| 1978 | 7 | 138 | John Spencer | |
| 1977 | 6 | 135 | John Spencer |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # World Championship (Crucible) data. | |
| # Source: https://www.snooker.org/Plr/wc_centuries.shtml | |
| # | |
| # Two figures: century counts (uniform markers) and highest break (147s accent). | |
| # Styling: Tufte-oriented (see SKILL.md). | |
| breaks <- read.csv("breaks.csv", stringsAsFactors = FALSE) | |
| library(ggplot2) | |
| r_cent <- cor(breaks$Year, breaks$Centuries) | |
| breaks$is147 <- !is.na(breaks$High) & breaks$High == 147 | |
| theme_tufte_snooker <- function() { | |
| theme_minimal(base_size = 11) + | |
| theme( | |
| plot.background = element_rect(fill = "#fffff8", colour = NA), | |
| panel.background = element_rect(fill = "#fffff8", colour = NA), | |
| panel.grid.major.x = element_blank(), | |
| panel.grid.minor = element_blank(), | |
| panel.grid.major.y = element_line(colour = "#eeeeee", linewidth = 0.35), | |
| panel.border = element_blank(), | |
| axis.line.x.bottom = element_line(colour = "#cccccc", linewidth = 0.4), | |
| axis.line.y.left = element_line(colour = "#cccccc", linewidth = 0.4), | |
| axis.title = element_text(family = "sans", size = 10, colour = "#666666"), | |
| axis.text = element_text(family = "sans", size = 9, colour = "#666666"), | |
| plot.title = element_text( | |
| family = "serif", face = "bold", size = 13.5, colour = "#111111", | |
| margin = margin(b = 6) | |
| ), | |
| plot.subtitle = element_text(family = "serif", size = 10, colour = "#666666", lineheight = 1.35), | |
| plot.caption = element_text(size = 8, colour = "#666666", hjust = 0, lineheight = 1.35), | |
| axis.minor.ticks.x.bottom = element_line(colour = "#cccccc", linewidth = 0.25), | |
| axis.minor.ticks.length.x.bottom = grid::unit(1.6, "mm"), | |
| axis.ticks.x.bottom = element_line(colour = "#cccccc", linewidth = 0.4), | |
| ) | |
| } | |
| # X-axis: label every 5 years; extra short ticks on decade years (1980, 1990, …) as anchors | |
| yr_max <- max(breaks$Year) | |
| x_years <- seq(1975, ceiling(yr_max / 5) * 5, 5) | |
| x_decades <- seq(1980, ceiling(yr_max / 10) * 10, 10) | |
| x_scale <- function() { | |
| scale_x_continuous( | |
| breaks = x_years, | |
| minor_breaks = x_decades, | |
| guide = guide_axis(minor.ticks = TRUE) | |
| ) | |
| } | |
| g_centuries <- ggplot(breaks, aes(Year, Centuries)) + | |
| geom_smooth(method = "lm", se = FALSE, linewidth = 0.45, colour = "#666666", formula = y ~ x) + | |
| geom_point(colour = "#666666", shape = 1, size = 2, stroke = 0.6) + | |
| x_scale() + | |
| labs( | |
| title = "Century breaks at the Crucible rose across the modern era", | |
| subtitle = paste0( | |
| "100+ breaks per World Championship (1977–", max(breaks$Year), "). ", | |
| "Year vs count r ≈ ", sprintf("%.2f", r_cent), "." | |
| ), | |
| x = "Year", | |
| y = "Centuries", | |
| caption = "Data: snooker.org Crucible centuries list · by @iamreddave" | |
| ) + | |
| theme_tufte_snooker() | |
| g_high <- ggplot(breaks, aes(Year, High)) + | |
| geom_line(colour = "#dddddd", linewidth = 0.35, aes(group = 1), na.rm = TRUE) + | |
| geom_point(data = subset(breaks, !is.na(High) & !is147), colour = "#666666", size = 1.9) + | |
| geom_point(data = subset(breaks, is147), colour = "#e41a1c", size = 2.4) + | |
| x_scale() + | |
| labs( | |
| title = "Tournament high break: many years hit the 147 maximum", | |
| subtitle = "Highest clearance at each World Championship. Red = 147 (table maximum).", | |
| x = "Year", | |
| y = "High break (points)", | |
| caption = "Data: snooker.org Crucible centuries list · by @iamreddave" | |
| ) + | |
| theme_tufte_snooker() | |
| dir.create("figures", showWarnings = FALSE) | |
| ggsave("figures/snooker_centuries.png", g_centuries, width = 9, height = 6, dpi = 150, bg = "#fffff8") | |
| ggsave("figures/snooker_high_break.png", g_high, width = 9, height = 6, dpi = 150, bg = "#fffff8") | |
| message("Wrote figures/snooker_centuries.png") | |
| message("Wrote figures/snooker_high_break.png") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment