---
title: "Untitled"
author: "RN7"
date: "1/19/2020"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

# pkgs

```{r, message=FALSE, warning=FALSE}
pacman::p_load(tidyverse, polite, scales, ggimage, 
               ggforce, ggtext,
               rvest, glue, extrafont, ggrepel, magick)
loadfonts()
```

## add_logo

```{r}
add_logo <- function(plot_path, logo_path, logo_position, 
                     logo_scale = 10){

    # Requires magick R Package https://github.com/ropensci/magick

    # Useful error message for logo position
    if (!logo_position %in% c("top right", "top left", "bottom right", "bottom left")) {
        stop("Error Message: Uh oh! Logo Position not recognized\n  Try: logo_positon = 'top left', 'top right', 'bottom left', or 'bottom right'")
    }

    # read in raw images
    plot <- magick::image_read(plot_path)
    logo_raw <- magick::image_read(logo_path)

    # get dimensions of plot for scaling
    plot_height <- magick::image_info(plot)$height
    plot_width <- magick::image_info(plot)$width

    # default scale to 1/10th width of plot
    # Can change with logo_scale
    logo <- magick::image_scale(logo_raw, as.character(plot_width/logo_scale))

    # Get width of logo
    logo_width <- magick::image_info(logo)$width
    logo_height <- magick::image_info(logo)$height

    # Set position of logo
    # Position starts at 0,0 at top left
    # Using 0.01 for 1% - aesthetic padding

    if (logo_position == "top right") {
        x_pos = plot_width - logo_width - 0.01 * plot_width
        y_pos = 0.01 * plot_height
    } else if (logo_position == "top left") {
        x_pos = 0.01 * plot_width
        y_pos = 0.01 * plot_height
    } else if (logo_position == "bottom right") {
        x_pos = plot_width - logo_width - 0.01 * plot_width
        y_pos = plot_height - logo_height - 0.01 * plot_height
    } else if (logo_position == "bottom left") {
        x_pos = 0.01 * plot_width
        y_pos = plot_height - logo_height - 0.01 * plot_height
    }

    # Compose the actual overlay
    magick::image_composite(plot, logo, offset = paste0("+", x_pos, "+", y_pos))
}
```



# La Liga data

- Save "Player Standard Stats" & "Squad Standard Stats" as a `.csv` file or whatever you prefer.
- https://fbref.com/en/comps/20/passing/Bundesliga-Stats

## advanced stats


```{r}
laliga_player_goalkeeping_stats_MD26_raw <- read_csv(here::here("data/laliga_player_goalkeeping_stats_MD26.csv"),
                                  skip = 1, col_names = TRUE) %>% 
    select(-Matches, -Rk)

laliga_player_goalkeeping_stats_MD26 <- laliga_player_goalkeeping_stats_MD26_raw %>% 
  rename_at(vars(17:19), 
            ~ glue::glue("launch_{colnames(laliga_player_goalkeeping_stats_MD26_raw)[17:19]}")) %>% 
  rename_at(vars(20:23), 
            ~ glue::glue("pass_{colnames(laliga_player_goalkeeping_stats_MD26_raw)[20:23]}")) %>% 
  rename_at(vars(24:26), 
            ~ glue::glue("goalkick_{colnames(laliga_player_goalkeeping_stats_MD26_raw)[24:26]}")) %>% 
  rename_at(vars(27:29), 
            ~ glue::glue("crosses_{colnames(laliga_player_goalkeeping_stats_MD26_raw)[27:29]}"))


laliga_player_goalkeeping_stats_MD26 <- laliga_player_goalkeeping_stats_MD26 %>% 
  rename_all(~str_replace_all(colnames(laliga_player_goalkeeping_stats_MD26), "_[0-9]", "")) %>% 
  rename(PSxGper90 = `/90`)

glimpse(laliga_player_goalkeeping_stats_MD26)
```


## regular stats

```{r}
laliga_player_regular_goalkeeping_stats_MD26_raw <- read_csv(here::here("data/laliga_player_regular_goalkeeping_stats_MD26.csv"), skip = 1, col_names = TRUE) %>% 
    select(-Matches, -Rk)

laliga_player_regular_goalkeeping_stats_MD26 <- laliga_player_regular_goalkeeping_stats_MD26_raw %>% 
  separate(Player, into = c("fullname", "allname"), 
           sep = "\\\\") %>% 
  separate(fullname, into = c("firstname", "lastname"),
           sep = "\\s", extra = "merge", remove = FALSE) %>%
  mutate(fname = str_extract(firstname, "[A-Z]{1}")) %>% 
  ## players like Fabinho listed without Tavares last name
  mutate(player = if_else(is.na(lastname), firstname, lastname)) %>% 
  mutate(player = case_when(
    !is.na(lastname) ~ glue("{fname}. {lastname}"),
    TRUE ~ firstname)) %>% 
  select(-firstname, -fname, -lastname, -allname)


laliga_player_regular_goalkeeping_stats_MD26 %>% 
  mutate(SoTAp90 = (SoTA / Min) * 90) %>% 
  filter(Min >= 1080) %>% 
  View()

glimpse(laliga_player_regular_goalkeeping_stats_MD26)
```


## clean

```{r}
laliga_player_goalkeeping_MD26_clean <- laliga_player_goalkeeping_stats_MD26 %>% 
  separate(Player, into = c("fullname", "allname"), sep = "\\\\") %>%   separate(fullname, into = c("firstname", "lastname"),
           sep = "\\s", extra = "merge",
           remove = FALSE) %>%
  mutate(fname = str_extract(firstname, "[A-Z]{1}")) %>% 
  ## players like Fabinho listed without Tavares last name
  mutate(player = if_else(is.na(lastname), firstname, lastname)) %>% 
  mutate(player = case_when(
    !is.na(lastname) ~ glue("{fname}. {lastname}"),
    TRUE ~ firstname)) %>% 
  left_join(laliga_player_regular_goalkeeping_stats_MD26) %>% 
  mutate(
    min = `90s` * 90,
    GSAA = PSxG - GA,
    GSAAper90 = (GSAA / min) * 90,
    `xSave%` = (SoTA - PSxG) / SoTA,
    GSAA_perc = `Save%` - `xSave%`,
    minPerSave = min / Saves) %>% 
  ## GSAA %: (SoTA - PSxG) / SoTA
  rename(team_name = Squad) %>% 
  ## keep fullname so can differentiate A. Gomes (Andre/Angel), etc.
  select(-`90s`, -firstname, -fname, -lastname, -allname)

glimpse(laliga_player_goalkeeping_MD26_clean)
```





```{r}
## save
saveRDS(laliga_player_goalkeeping_MD26_clean, 
        file = glue("{here::here()}/data/laliga_player_goalkeeping_MD26_clean.RDS"))

laliga_player_goalkeeping_MD26_clean <- readRDS(
  file = glue("{here::here()}/data/laliga_player_goalkeeping_MD26_clean.RDS"))
```

# plot

```{r}
laliga_player_goalkeeping_MD26_clean %>% 
  filter(min >= 1080) %>% 
  summarize(avg_psxgper90 = median(PSxGper90),
            avg_GA = median(GA),
            avg_GSAA = median(GSAA),
            avg_SV_perc = median(`Save%`),
            avg_xSV_perc = median(`xSave%`),
            avg_minperSave = median(minPerSave),
            avg_GSAA_perc = median(GSAA_perc))

laliga_player_goalkeeping_MD26_clean %>% 
  filter(min >= 1080) %>% 
  summarize(avg_psxgper90 = mean(PSxGper90),
            avg_GA = mean(GA),
            avg_GSAA = mean(GSAA))
```


```{r}
bad_box <- data.frame(
  xmin = -Inf, xmax = 0, 
  ymin = -Inf, ymax = 34.92)

chance_creation_box <- data.frame(
  xmin = -Inf, xmax = 0, 
  ymin = 34.92, ymax = Inf)

midfield_progress_box <- data.frame(
  xmin = 0, xmax = Inf, 
  ymin = -Inf, ymax = 34.92)

dual_box <- data.frame(
  xmin = 0, xmax = Inf, 
  ymin = 34.92, ymax = Inf)
```





## Minutes / Save  vs. GSAA

```{r}
laliga_gk <- laliga_player_goalkeeping_MD26_clean %>% 
  filter(min >= 1080) %>% 
  mutate(fillcol = case_when(
    GSAA_perc < 0 & minPerSave < 34.92 ~ "red",
    GSAA_perc > 0 & minPerSave < 34.92 ~ "yellow",
    GSAA_perc < 0 & minPerSave > 34.92 ~ "orange",
    GSAA_perc > 0 & minPerSave > 34.92 ~ "green",
    TRUE ~ NA_character_),
    player = case_when(
      player == "NA. Remiro" ~ "A. Remiro", 
      TRUE ~ as.character(player)
    ))

laliga_gk %>% select(-c(3, 6, 8:11, 16:24, 26:31)) %>% View()
```

```{r}
point_cols <- c("yellow" = "yellow", "red" = "red",
                "orange" = "orange", "green" = "#228B22")
```


0.33 PSxG per Shot on Target 115 saves best in the league

```{r}
aitor_desc <- "Aitor Fernández has been having a stellar season preventing an otherwise woeful Levante team, who have the worst xGA & xG Difference in the league, from having to fight a relegation battle. Aitor is putting up an impressive 0.4 GSAA per 90 (1st) & +6.8 GSAA % (2nd), all the while being the busiest keeper in the league, forced to make a save every 20.3 minutes! He has also prevented 10.4 goals that the post-shot model expected an average GK to concede."

simon_desc <- "Athletic Bilbao have conceded 22 goals this season, only Atlético Madrid & Real Madrid have conceded less, in large part due to the excellent performances of Unai Simón. With his strong numbers, +7.4 GSAA % (best in La Liga), 5.2 GSAA (3rd best), & 72.9% Save % (4th best) the Basques could be in contention for an European spot if they could figure out how to supplement their stout defense with more goals (tied 5th worst goals scored)."

oblak_desc <- "The winner of the last 4 Zamora Trophies is having a slight down season, but only in comparison to his God-like form in the past few years. Oblak still has the 2nd best GA per 90 at 0.74 & 3rd best Save % of 73.6 in the league but he has given up 2.7 goals on shots that the post-shot model expected an average GK to save (5th worst)."
```

La Real & Real Betis are on 25 matches

```{r fig.width = 16, fig.height = 10}
laliga_goalkeeping_MD26_plot <- laliga_gk %>% 
  ggplot(aes(x = GSAA_perc, y = minPerSave)) +
  geom_vline(xintercept = 0) +
  geom_hline(yintercept = 34.92) +
  ## area fills
  geom_rect(data = chance_creation_box,
            aes(x = NULL, y = NULL,
                xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax),
            fill = "orange", alpha = 0.1) +
  geom_rect(data = bad_box,
            aes(x = NULL, y = NULL,
                xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax),
            fill = "red", alpha = 0.1) +
  geom_rect(data = midfield_progress_box,
            aes(x = NULL, y = NULL,
                xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax),
            fill = "yellow", alpha = 0.2) +
  geom_rect(data = dual_box,
            aes(x = NULL, y = NULL,
                xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax),
            fill = "green", alpha = 0.1) +
  ## area labels
  ## LEFT
  annotate("text", family = "Roboto Condensed", fontface = "bold",
           x = -0.075, y = 19, 
           color = "red", size = 6,
           label = "Busy & Saving Less Than Average GK") +
  annotate("text", family = "Roboto Condensed", fontface = "bold",
           x = -0.075, y = 58, 
           color = "orange", size = 6,
           label = "Not Busy & Saving Less Than Average GK") +
  ## RIGHT
  annotate( # #7f7f00  #228B22 #CCCC00
    "text", family = "Roboto Condensed", fontface = "bold",
    x = 0.105, y = 58, 
    color = "#228B22", size = 6,
    label = "Not Busy & Saving More Than Average GK") +
  annotate(
    "text", family = "Roboto Condensed", fontface = "bold",
    x = 0.105, y = 19, 
    color = "#7f7f00", size = 6,
    label = "Busy & Saving More Than Average GK") +
  ## avg minutes per save
  annotate(
    "text", family = "Roboto Condensed", fontface = "bold",
    x = 0.125, y = 36, 
    hjust = 0, color = "grey20", size = 4.5,
    label = "Average: 34.92 Minutes per Save") +
  ## player data
  geom_point(aes(fill = factor(fillcol)), 
             shape = 21, size = 3) +
  scale_fill_manual(values = point_cols,
                    guide = NULL) +
  geom_text_repel(
    data = laliga_gk %>% 
      filter(!player %in% c("J. Oblak", "A. Fernández",
                            "U. Simón", "T. Courtois", "D. Soria")),
    aes(label = player, family = "Roboto Condensed", 
        fontface = "bold", 
        segment.color = factor(fillcol)),
    min.segment.length = 0.5, seed = 15, size = 5,
    point.padding = 0.6, color = "grey20") +
  # Aitor Fernandez
  geom_mark_hull(
    aes(filter = player == "A. Fernández",
        label = "Aitor Fernández (Levante)",
        description = aitor_desc),
    expand = unit(2.5, "mm"), con.cap = unit(0, "mm"),
    con.colour = "grey20", color = "grey20", 
    label.width = unit(190, 'mm'), label.buffer = unit(1, "mm"),
    label.family = "Roboto Condensed", label.fontsize = c(14, 12),
    label.colour = "grey20", label.fill = "#FFFF66") +
  # Unai Simon
  geom_mark_hull(
    aes(filter = player == "U. Simón",
        label = "Unai Simón (Athletic Bilbao)",
        description = simon_desc), #position = position_nudge(x = 2),
    expand = unit(2.5, "mm"), con.cap = unit(0, "mm"),
    con.colour = "#228B22", color = "#228B22", 
    label.width = unit(140, 'mm'), label.buffer = unit(1, "mm"),
    label.family = "Roboto Condensed", label.fontsize = c(14, 12),
    label.colour = "grey20", label.fill = "#cce5cc") +
  # J. Oblak
  geom_mark_hull(
    aes(filter = player == "J. Oblak",
        label = "Jan Oblak (Atlético Madrid)",
        description = oblak_desc),
    expand = unit(2.5, "mm"), con.cap = unit(0, "mm"), con.type = "straight",
    con.colour = "orange", color = "orange", radius = unit(1, "mm"),
    label.width = unit(130, 'mm'), label.buffer = unit(10, "mm"),
    label.family = "Roboto Condensed", label.fontsize = c(14, 12),
    label.colour = "grey20", label.fill = "#ffe5cc") +
  geom_text(
    data = laliga_gk %>%
      filter(player == "T. Courtois"),
    aes(label = player, family = "Roboto Condensed", fontface = "bold"),
    size = 5, color = "grey20",
    nudge_x = -0.01, nudge_y = 1) +
  geom_text(
    data = laliga_gk %>%
      filter(player == "D. Soria"),
    aes(label = player, family = "Roboto Condensed", fontface = "bold"),
    size = 5, color = "grey20",
    nudge_x = -0.01, nudge_y = -0.3) +
  scale_x_continuous(labels = scales::percent,
                     breaks = seq(-0.15, 0.2, 0.05),
                     limits = c(-0.15, 0.21),
                     expand = c(0.01, 0)) +
  scale_y_continuous(breaks = seq(15, 55, 10),
                     limits = c(18, 60),
                     expand = c(0.01, 0)) +
  ## #3d195b   #4B0082
  labs(title = "<b>Goalkeeper Performance & Workload:</b> <b style='color: red'>La Liga (2019-2020)</b>",
       subtitle = glue::glue("
                             March 5th, 2020 | Matchday 26 | Minimum 1080 Minutes Played
                             <p>GSAA %: Whether a GK has saved more/less than the post-shot model expected an average GK to save (Actual Save % - Expected Save %)"),
       x = "Goals Saved Above Average Percentage (GSAA %)", 
       y = "Average Minutes per Save",
       caption = glue::glue("
                            Data: FBref | StatsBomb
                            Graphic: Ryo Nakagawara (Twitter: @R_by_Ryo)")) +
  theme_minimal() +
  theme(text = element_text(family = "Roboto Condensed"),
        plot.title = element_markdown(size = 22),
        plot.subtitle = element_markdown(size = 18),
        plot.caption = element_text(size = 16),
        axis.title = element_text(size = 16),
        axis.text = element_text(size = 14))

laliga_goalkeeping_MD26_plot
```




## save

```{r}
ggsave(plot = laliga_goalkeeping_MD26_plot, 
       here::here("La Liga 2019-2020/output/laliga_goalkeeping_1920_MD26.png"),
       height = 10, width = 16)
```

```{r}
plot_logo <- add_logo(
  plot_path = here::here("La Liga 2019-2020/output/laliga_goalkeeping_1920_MD26.png"),
  logo_path = "https://upload.wikimedia.org/wikipedia/en/3/35/La_Liga.png",
  logo_position = "top right",
  logo_scale = 17)

plot_logo
```

```{r}
image_write(image = plot_logo, 
            here::here("La Liga 2019-2020/output/laliga_goalkeeping_1920_MD26_logo.png"))
```





```{r fig.width = 14, fig.height = 10}
laliga_gk %>% 
  ggplot(aes(x = GSAA_perc, y = minPerSave)) +
  geom_vline(xintercept = 0) +
  geom_hline(yintercept = 34.92) +
  ## area fills
  geom_rect(data = chance_creation_box,
            aes(x = NULL, y = NULL,
                xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax),
            fill = "orange", alpha = 0.1) +
  geom_rect(data = bad_box,
            aes(x = NULL, y = NULL,
                xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax),
            fill = "red", alpha = 0.1) +
  geom_rect(data = midfield_progress_box,
            aes(x = NULL, y = NULL,
                xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax),
            fill = "yellow", alpha = 0.2) +
  geom_rect(data = dual_box,
            aes(x = NULL, y = NULL,
                xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax),
            fill = "green", alpha = 0.1) +
  ## area labels
  ## LEFT
  annotate("text", family = "Roboto Condensed", fontface = "bold",
           x = -0.12, y = 19, 
           hjust = 0, color = "red", size = 6,
           label = "Busy & Saving Less Than Average GK") +
  annotate("text", family = "Roboto Condensed", fontface = "bold",
           x = -0.12, y = 54, 
           hjust = 0, color = "orange", size = 6,
           label = "Not Busy & Saving Less Than Average GK") +
  ## RIGHT
  annotate( # #7f7f00  #228B22 #CCCC00
    "text", family = "Roboto Condensed", fontface = "bold",
    x = 0.03, y = 54, 
    hjust = 0, color = "#228B22", size = 6,
    label = "Not Busy & Saving More Than Average GK") +
  annotate(
    "text", family = "Roboto Condensed", fontface = "bold",
    x = 0.03, y = 19, 
    hjust = 0, color = "#7f7f00", size = 6,
    label = "Busy & Saving More Than Average GK") +
  ## avg minutes per save
  annotate(
    "text", family = "Roboto Condensed", fontface = "bold",
    x = -0.15, y = 33.5, 
    hjust = 0, color = "grey20", size = 4,
    label = "Average: 34.92 Minutes per Save") +
  ## player data
  geom_point(aes(fill = factor(fillcol)), 
             shape = 21, size = 3) +
  scale_fill_manual(values = point_cols,
                    guide = NULL) +
  geom_text_repel(
    data = laliga_gk %>% 
      filter(!player %in% c("Alisson", "K. Arrizabalaga",
                            "A. Gunn")),
    aes(label = player, family = "Roboto Condensed", 
        fontface = "bold", 
        segment.color = factor(fillcol)),
    min.segment.length = 0.3, seed = 15, size = 5,
    point.padding = 0.6, color = "grey20") +
  ## #3d195b   #4B0082
  labs(title = "<b>Goalkeeper Performance & Workload:</b> <b style='color: red'>La Liga (2019-2020)</b>",
       subtitle = glue::glue("
                             March 5th, 2020 | Matchday 26 | Minimum 1080 Minutes Played
                             <p>GSAA %: Whether a GK has saved more/less than the post-shot model expected an average GK to save (Actual Save % - Expected Save %)"),
       x = "Goals Saved Above Average Percentage (GSAA %)", 
       y = "Average Minutes per Save",
       caption = glue::glue("
                            Data: FBref | StatsBomb
                            Ryo Nakagawara, Twitter: @R_by_Ryo")) +
  theme_minimal() +
  theme(text = element_text(family = "Roboto Condensed"),
        plot.title = element_markdown(size = 20),
        plot.subtitle = element_markdown(size = 16),
        plot.caption = element_text(size = 14),
        axis.title = element_text(size = 14),
        axis.text = element_text(size = 12))
```





