La dataviz dont nous nous sommes inspiré est disponible à l’adresse https://insights.datylon.com/stories/oDHVikVxaCaCGWRFGMdPgA.
library(readxl)
library(tidyverse)
library(magick)
## Linking to ImageMagick 6.9.12.3
## Enabled features: cairo, fontconfig, freetype, heic, lcms, pango, raw, rsvg, webp
## Disabled features: fftw, ghostscript, x11
scoring_data <- read_excel("default_workbook.xlsx",
sheet = "Scoring data") %>%
rename(name = NAME, pts = PTS, fgp = "FG%", group = Group) %>%
mutate(pts = as.double(pts),
fgp = as.double(fgp))
scoring_data
## # A tibble: 581 × 4
## name fgp pts group
## <chr> <dbl> <dbl> <chr>
## 1 Joel Embiid 49.9 30.6 Ineffective high-scorer
## 2 LeBron James 52.4 30.3 Effective high-scorer
## 3 Giannis Antetokounmpo 55.3 29.9 Effective high-scorer
## 4 Kevin Durant 51.8 29.9 Effective high-scorer
## 5 Luka Doncic 45.7 28.4 Ineffective high-scorer
## 6 Trae Young 46 28.4 Ineffective high-scorer
## 7 DeMar DeRozan 50.4 27.9 Effective high-scorer
## 8 Kyrie Irving 46.9 27.4 Ineffective high-scorer
## 9 Ja Morant 49.3 27.4 Ineffective high-scorer
## 10 Nikola Jokic 58.3 27.1 Effective high-scorer
## # … with 571 more rows
Pour les images du tableau, il faut créer manuellement un data.frame. On va télécharger chaque image dans un fichier temporaire car flextable ne gère que les images disponible localement.
head_shot <- tibble::tribble(
~name, ~url,
"Joel Embiid", "https://cdn.nba.com/headshots/nba/latest/1040x760/203954.png",
"LeBron James", "https://cdn.nba.com/headshots/nba/latest/1040x760/2544.png",
"Giannis Antetokounmpo", "https://cdn.nba.com/headshots/nba/latest/1040x760/203507.png",
"Kevin Durant", "https://cdn.nba.com/headshots/nba/latest/1040x760/201142.png",
"Trae Young", "https://cdn.nba.com/headshots/nba/latest/1040x760/1629027.png",
"Luka Doncic", "https://cdn.nba.com/headshots/nba/latest/1040x760/1629029.png"
) %>%
mutate(url = map_chr(url, function(z) {
path <- tempfile(fileext = ".png")
image_read(z) %>%
image_resize(geometry = "144x") %>%
image_write(path = path)
path
}))
Le tableau ‘Q3_data’ va être utilisé lors de la construction du ggplot.
Q3_data <- summarise(scoring_data,
pts = quantile(pts, probs = .75),
fgp = quantile(fgp, probs = .75)
)
Q3_data
## # A tibble: 1 × 2
## pts fgp
## <dbl> <dbl>
## 1 11.3 50
Le tableau ‘scoring_highlight’ va être le tableau principal.
scoring_highlight <- scoring_data %>%
arrange(desc(pts), desc(fgp)) %>%
slice_max(pts, n = 6) %>%
left_join(head_shot, by = "name")
scoring_highlight
## # A tibble: 6 × 5
## name fgp pts group url
## <chr> <dbl> <dbl> <chr> <chr>
## 1 Joel Embiid 49.9 30.6 Ineffective high-scorer /var/folders/08/2qd…
## 2 LeBron James 52.4 30.3 Effective high-scorer /var/folders/08/2qd…
## 3 Giannis Antetokounmpo 55.3 29.9 Effective high-scorer /var/folders/08/2qd…
## 4 Kevin Durant 51.8 29.9 Effective high-scorer /var/folders/08/2qd…
## 5 Trae Young 46 28.4 Ineffective high-scorer /var/folders/08/2qd…
## 6 Luka Doncic 45.7 28.4 Ineffective high-scorer /var/folders/08/2qd…
theme_scorer <- function(x) {
border_remove(x) %>%
valign(valign = "center", part = "all") %>%
align(align = "center", part = "all") %>%
fontsize(part = "all", size = 20) %>%
bold(part = "header", bold = TRUE) %>%
bold(part = "body", j = 1, bold = TRUE) %>%
color(color = "#b17268", part = "header") %>%
bg(part = "header", bg = "transparent")
}
ft <- as_grouped_data(scoring_highlight, groups = c("name"), expand_single = TRUE) %>%
as_flextable(hide_grouplabel = TRUE, col_keys = c("url", "fgp", "pts")) %>%
set_header_labels(url = "", fgp = "Field goal", pts = "Points") %>%
mk_par(j = "url", i = ~ !is.na(url),
value = as_paragraph(
as_image(url, width = .75, height = 0.54),
"\n",
as_i(name)
)
) %>%
theme_scorer() %>%
align(i = ~!is.na(name), align = "left", part = "body") %>%
bg(i = ~ group %in% "Effective high-scorer", bg = "#f8b26399") %>%
bg(i = ~ group %in% "Ineffective high-scorer", bg = "#b1726899") %>%
hline(i = rep(c(FALSE, TRUE, FALSE, TRUE), length = nrow_part(.))) %>%
autofit()
Nous pouvons déjà transformer le tableau en un graphique.
plot(ft, fit = "fixed", scaling = "fixed", just = "centre")
gg <- scoring_data %>%
ggplot(mapping = aes(x = fgp, y = pts, color = group)) +
geom_point(size = 3, alpha = .7, show.legend = FALSE) +
scale_color_manual(
values = c(
"Effective high-scorer" = "#f8b263",
"Ineffective low-scorer" = "#819eb2",
"Ineffective high-scorer" = "#b17268",
"Effective low-scorer" = "#dad162"
)) +
scale_y_continuous(limits = c(0, 40)) +
geom_hline(data = Q3_data, aes(yintercept = `pts`)) +
geom_vline(data = Q3_data, aes(xintercept = fgp)) +
ggforce::geom_mark_rect(data = scoring_highlight,
mapping = aes(color = NULL),
expand = unit(3, "mm"),
show.legend = FALSE) +
annotate(geom = "text", x = 100, y = Q3_data$pts,
label = "Effective\nhigh-scorer", color = "#f8b263",
hjust = 1, vjust = -1) +
annotate(geom = "text", x = 100, y = Q3_data$pts,
label = "Effective\nlow-scorer", color = "#dad162",
hjust = 1, vjust = 2) +
annotate(geom = "text", x = 0, y = Q3_data$pts,
label = "Low-Effective\nhigh-scorer", color = "#819eb2",
hjust = 0.2, vjust = 2) +
annotate(geom = "text", x = 0, y = Q3_data$pts,
label = "Low-Effective\nlow-scorer", color = "#b17268",
hjust = .2, vjust = -1) +
theme_minimal()
gg
library(patchwork)
gg + inset_element(
gen_grob(ft, fit = "width"),
left = 0.65, bottom = .65,
right = 1, top = 1
) + theme(
plot.background = element_rect(fill = "transparent"),
panel.background = element_rect(fill = "transparent")
)
gg + gen_grob(ft, fit = "width")
gg + gen_grob(ft, fit = "width") + plot_layout(ncol = 2, widths = c(3, 1))