1

I am trying to plot a pass network on a football pitch. After the cleaning the data it looks like this

structure(list(surname_sender = c("Ajite", "Dikmen", "Dikmen", 
"Dikmen", "Dikmen", "Jylmaz", "Jylmaz", "Jylmaz", "Kandejas", 
"Kandejas", "Kandejas", "Kandejas", "Kizildag", "Kizildag", "Kizildag", 
"Kizildag", "Kizildag", "Motta", "Motta", "Motta", "Motta", "Motta", 
"Motta", "Nordfel'dt", "Nordfel'dt", "Poloma", "Sio", "Ture", 
"Ture", "Ture", "Ture", "Ture", "Uhansson", "Uhansson", "Uhansson", 
"Uhansson"), surname_receiver = c("Poloma", "Kizildag", "Poloma", 
"Ture", "Uhansson", "Kandejas", "Poloma", "Uhansson", "Motta", 
"Nordfel'dt", "Ture", "Uhansson", "Dikmen", "Motta", "Nordfel'dt", 
"Ture", "Uhansson", "Dikmen", "Jylmaz", "Kizildag", "Poloma", 
"Ture", "Uhansson", "Ture", "Uhansson", "Ture", "Dikmen", "Jylmaz", 
"Kandejas", "Kizildag", "Motta", "Poloma", "Kandejas", "Kizildag", 
"Sio", "Uhansson"), passes = c(4L, 4L, 4L, 4L, 6L, 4L, 5L, 4L, 
4L, 5L, 4L, 9L, 10L, 6L, 4L, 5L, 8L, 5L, 4L, 6L, 4L, 4L, 5L, 
4L, 6L, 13L, 5L, 5L, 4L, 9L, 8L, 7L, 14L, 8L, 5L, 4L), mean_passer_x = c(64.7, 
44.41875, 44.41875, 44.41875, 44.41875, 68.725, 68.725, 68.725, 
75.2919444444445, 75.2919444444445, 75.2919444444445, 75.2919444444445, 
29.5423333333333, 29.5423333333333, 29.5423333333333, 29.5423333333333, 
29.5423333333333, 44.31, 44.31, 44.31, 44.31, 44.31, 44.31, 8.60416666666667, 
8.60416666666667, 58.6384615384615, 52.46, 38.2090952380952, 
38.2090952380952, 38.2090952380952, 38.2090952380952, 38.2090952380952, 
51.7642857142857, 51.7642857142857, 51.7642857142857, 51.7642857142857
), mean_passer_y = c(46.9, 38.7083333333333, 38.7083333333333, 
38.7083333333333, 38.7083333333333, 35.3533333333333, 35.3533333333333, 
35.3533333333333, 10.7833333333333, 10.7833333333333, 10.7833333333333, 
10.7833333333333, 23.6785, 23.6785, 23.6785, 23.6785, 23.6785, 
34.6552777777778, 34.6552777777778, 34.6552777777778, 34.6552777777778, 
34.6552777777778, 34.6552777777778, 32.2166666666667, 32.2166666666667, 
65.3, 25.7, 46.9388571428571, 46.9388571428571, 46.9388571428571, 
46.9388571428571, 46.9388571428571, 7.25, 7.25, 7.25, 7.25)), row.names = c(NA, 
-36L), class = c("tbl_df", "tbl", "data.frame"))

The solution that I have found seems quite boring and silly :)

library(tidyverse)
library(ggsoccer)
library(ggrepel)

 ggplot(df2, aes(mean_passer_x, mean_passer_y)) +
   annotate_pitch(dimensions = pitch_custom) +
  geom_point(color = "red") +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
              data = . %>% filter(surname_sender %in% c("Motta", "Kizildag"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Motta", "Uhansson"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Motta", "Ture"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Motta", "Sio"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Motta", "Dikmen"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Motta", "Kandejas"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Motta", "Jylmaz"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, color= "red", alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Kizildag", "Ture"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, color= "red", alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Nordfel'dt", "Ture"))) +
  geom_line(aes(mean_passer_x, mean_passer_y, size = passes, color= "red", alpha = 0.2),
            data = . %>% filter(surname_sender %in% c("Nordfel'dt", "Kizildag"))) +
  geom_text(aes(label = surname_sender) ) +
  theme_pitch() 

The end result is

enter image description here

All I want to do is to connect all of the points(players) with each other by lines and define the line size according to the number of passes.

Thanks a lot

tjebo
  • 21,977
  • 7
  • 58
  • 94
Emre Toros
  • 51
  • 1
  • 5
  • 1
    Hi Emre, please do not provide screen shots of your data. Instead, provide it as text by clicking the [edit] button under your post. Either copy the output of the `dput(df2)` command and paste the output into your question (preferred) or paste the tab delimited data from a spreadsheet program. Please see [How to make a great R reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) for more information. – Ian Campbell Jan 09 '21 at 16:00

1 Answers1

3

Not completely sure about your final result. However, as far as I get it your data needs some additional wrangling before you can plot your passing network. The issue is that each row of your df contains only the position of the "sender" but not of the receiver. Therefore

  1. I first extracted the names and (mean) positions of all players
  2. I join the dataset with the positions back to your original df where I join on the receiving players name. As a result each row now contains both the position of the sending and the receiving player.
  3. After doing so you can plot your network easily by making use of geom_segment and map the number of passes on size. Additionally I mapped the surname_receiver on color to make the direction of passes visible.
library(ggplot2)
library(ggsoccer)
library(ggrepel)
library(dplyr)

pos_player <- df2 %>% 
  select(name = surname_sender, pos_x = mean_passer_x, pos_y = mean_passer_y) %>% 
  distinct()

df2 %>% 
  left_join(pos_player, by = c("surname_receiver" = "name")) %>% 
  group_by(surname_sender) %>% 
  mutate(is_label = row_number() == 1) %>% 
  arrange(desc(passes)) %>% 
  ggplot(aes(x = mean_passer_x, y = mean_passer_y)) +
  annotate_pitch() +
  geom_segment(aes(xend = pos_x, yend = pos_y, size = passes, color = surname_sender), alpha = 0.5) +
  geom_point(color = "red") +
  ggrepel::geom_text_repel(aes(label = ifelse(is_label, surname_sender, "")) ) +
  scale_color_brewer(type = "qual", palette = "Set3") +
  theme_pitch()

stefan
  • 90,330
  • 6
  • 25
  • 51
  • Thanks a lot! I dont know if there is a better way to reach that plot, but the original data before the cleaning that I have done can be found at https://drive.google.com/file/d/1eXmEFy4TC7B6kw3rcp8DE6vzUkVO-pWn/view?usp=sharing Any suggestions to do this in an alternative way is highly welcomed :) – Emre Toros Jan 09 '21 at 19:18