Учебники по созданию снимков, проходов и тепловых карт

Введение

Футбольная аналитика быстро развивалась в последние годы. С данными мы можем понять игру с другой точки зрения.

В этой статье я покажу вам, как визуализировать футбольные данные с помощью R. В конце этой статьи вы сможете создавать такие визуализации:

Без лишних слов, приступим!

Выполнение

Источник данных

Мы будем использовать открытые данные от StatsBomb, у меня есть разрешение на использование данных в качестве примера. StatsBomb — футбольная аналитическая компания, которая предоставляет данные о событиях и аналитические услуги для футбольных клубов.

Поскольку данные о событиях отличаются от обычных табличных данных, StatsBomb предоставляет бесплатные данные, которые помогут нам узнать больше о том, как анализировать футбол с использованием данных.

Лиги, которые мы можем выбрать из открытых данных, — это Лига чемпионов УЕФА, чемпионат мира, индийская Суперлига и многие другие.

В этой статье мы создадим визуализацию на основе матча финала Лиги чемпионов 2012/13 между мюнхенской «Баварией» и дортмундской «Боруссией».

Формат данных StatsBomb похож на файл JSON, поэтому с его помощью будет сложно анализировать данные. Но, к счастью, мы можем легко получить данные с помощью функции под названием StatsBombR.

Установите и загрузите библиотеки

Нам нужно несколько библиотек, которые помогут нам создать визуализацию. Эти библиотеки:

  • StatsBombR => Получение данных StatsBomb
  • Tiduverse =› Библиотека, которая компилирует библиотеки для предварительной обработки и визуализации данных.
  • Ggsoccer =› Библиотека для создания футбольного поля в нашей визуализации.

Давайте установим библиотеку. Вот код для этого:

# Install the necessary libraries
install.packages('devtools')
devtools::install_github("statsbomb/SDMTools")
devtools::install_github("statsbomb/StatsBombR")
install.packages('tidyverse')
install.packages('ggsoccer')

После этого вы можете загрузить библиотеку, выполнив следующие строки кода:

# Load the libraries
library(tidyverse)
library(StatsBombR)
library(ggsoccer)

Теперь мы готовы запачкать руки.

Предварительно обработайте данные

Так как StatsBomb предоставляет открытые данные из разных лиг, нам необходимо указать идентификатор соревнования и сезон, который мы хотим проанализировать.

Во-первых, нам нужно просмотреть все соревнования, которые предоставляет StatsBomb. Вот код для этого:

# Retrieve all available competitions
Comp <- FreeCompetitions()

Из этого кода вы увидите фрейм данных, содержащий все лиги, которые они охватывают.

Как я уже говорил, мы будем анализировать матч между «Баварией» и «Боруссией» в финале Лиги чемпионов. Соответствующий идентификатор соревнования и сезон — 16 и 2012/2013 соответственно.

Давайте отфильтруем данные, запустив этот код ниже:

# Filter the competition
ucl_german <- Comp %>%
  filter(competition_id==16 & season_name=="2012/2013")

Затем мы извлекаем все матчи, соответствующие этой лиге и сезону. Вот код для этого:

# Retrieve all available matches
matches <- FreeMatches(ucl_german)

После того, как мы получим все совпадения, мы можем получить данные о событии, запустив эту строку кода:

# Retrieve the event data
events_df <- get.matchFree(matches)

И, наконец, мы очищаем данные. Вот код для этого:

# Preprocess the data
clean_df <- allclean(events_df)

Теперь у нас есть данные. Давайте создадим визуализации!

Карта проезда

Первая карта — проходная. Карта проходов показывает все проходы, созданные игроком или командой. В этом примере мы создадим карту проходов Томаса Мюллера.

Давайте отфильтруем данные, взяв все проходы, сделанные Мюллером. Вот код для этого:

# Passing Map
muller_pass <- clean_df %>%
  filter(player.name == 'Thomas Müller') %>%
  filter(type.name == 'Pass')

А теперь самое интересное. Для создания визуализации мы будем использовать библиотеку ggplot и ggsoccer. Вот код для создания базовой визуализации:

ggplot(muller_pass) +
  annotate_pitch(dimensions = pitch_statsbomb) +
  geom_segment(aes(x=location.x, y=location.y, xend=pass.end_location.x, yend=pass.end_location.y),
               colour = "coral",
               arrow = arrow(length = unit(0.15, "cm"),
                             type = "closed")) +
  labs(title="Thomas Muller's Passing Map",
       subtitle="UEFA Champions League Final 12/13",
       caption="Data Source: StatsBomb")

Если вы пользователь R, я думаю, вы знакомы с ggplot.

ggsoccer расширяет библиотеку ggplot, поэтому мы можем построить визуализацию данных о событиях, которые содержат начальные и конечные координаты.

Библиотека предоставляет annotate_pitch для создания футбольного поля и geom_segment для создания линий пасов, что вы можете видеть из приведенного выше кода. А остальное то, что вы видите на ggplot.

И вот результат:

Ну визуально не эстетично выглядит. Давайте добавим функцию темы, чтобы настроить внешний вид визуализации. Вот полный код вместе с функцией темы:

ggplot(muller_pass) +
  annotate_pitch(dimensions = pitch_statsbomb, fill='#021e3f', colour='#DDDDDD') +
  geom_segment(aes(x=location.x, y=location.y, xend=pass.end_location.x, yend=pass.end_location.y),
               colour = "coral",
               arrow = arrow(length = unit(0.15, "cm"),
                             type = "closed")) + 
  labs(title="Thomas Muller's Passing Map",
       subtitle="UEFA Champions League Final 12/13",
       caption="Data Source: StatsBomb") + 
  theme(
    plot.background = element_rect(fill='#021e3f', color='#021e3f'),
    panel.background = element_rect(fill='#021e3f', color='#021e3f'),
    plot.title = element_text(hjust=0.5, vjust=0, size=14),
    plot.subtitle = element_text(hjust=0.5, vjust=0, size=8),
    plot.caption = element_text(hjust=0.5),
    text = element_text(family="Geneva", color='white'),
    panel.grid = element_blank(),
    axis.title = element_blank(),
    axis.text = element_blank()
  )

И вот результат:

Теперь это выглядит великолепно!

Карта выстрелов

В этом разделе мы создадим карту бросков для обеих команд. Но мы нанесем удары, созданные каждым клубом, по разным координатам.

Поэтому мы создадим два фрейма данных с данными о бросках Баварии и Дортмунда. Давайте запустим эти строки кода:

dortmund_shot <- clean_df %>%
  filter(type.name == 'Shot') %>%
  filter(team.name == 'Borussia Dortmund') %>%
  select(player.name, location.x, location.y, shot.end_location.x, shot.end_location.y, shot.statsbomb_xg)
bayern_shot <- clean_df %>%
  filter(type.name == 'Shot') %>%
  filter(team.name == 'Bayern Munich') %>%
  select(player.name, location.x, location.y, shot.end_location.x, shot.end_location.y, shot.statsbomb_xg)

Создание карты выстрелов также похоже на создание карты проходов. Мы заменяем функцию geom_segment на функцию geom_point. Если вы знаете, это функция для построения точечной диаграммы.

Мы применяем функцию к каждому фрейму данных. А для данных выстрелов Дортмунда мы отражаем координаты x, вычитая значение на 120.

Взгляните на этот код:

ggplot() +
  annotate_pitch(dimensions = pitch_statsbomb, colour='white', fill='#021e3f') +
  geom_point(data=dortmund_shot, aes(x=location.x, y=location.y, size=shot.statsbomb_xg), color="red") +
  geom_point(data=bayern_shot, aes(x=120-location.x, y=location.y, size=shot.statsbomb_xg), color="yellow") +
  labs(
    title="Borussia Dortmund vs Bayern Munich",
    subtitle = "Shots Map | UEFA Champions League Final 2012/2013",
    caption="Data Source: StatsBomb"
  ) + 
  theme(
    plot.background = element_rect(fill='#021e3f', color='#021e3f'),
    panel.background = element_rect(fill='#021e3f', color='#021e3f'),
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    axis.text.x = element_blank(),
    axis.text.y = element_blank(),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    text = element_text(family="Geneva", color='white'),
    plot.title = element_text(hjust=0.5, vjust=0, size=14),
    plot.subtitle = element_text(hjust=0.5, vjust=0, size=8),
    plot.caption = element_text(hjust=0.5),
    plot.margin = margin(2, 2, 2, 2),
    legend.position = "none"
  )

Посмотрим на результат кода:

Тепловая карта давления

Наконец, мы создадим тепловую карту давления, проводимую мюнхенской Баварией. Давайте отфильтруем данные, используя эти строки кода:

# Pressure Heat Map
bayern_pressure <- clean_df %>%
  filter(team.name == 'Bayern Munich') %>%
  filter(type.name == 'Pressure')

Чтобы создать визуализацию, она аналогична предыдущей. Пожалуйста, взгляните на этот код:

ggplot(bayern_pressure) +
  annotate_pitch(dimensions = pitch_statsbomb, fill='#021e3f', colour='#DDDDDD') +
  geom_density2d_filled(aes(location.x, location.y, fill=..level..), alpha=0.4, contour_var='ndensity') +
  scale_x_continuous(c(0, 120)) +
  scale_y_continuous(c(0, 80)) +
  labs(title="Bayern Munich's Pressure Heat Map",
       subtitle="UEFA Champions League Final 12/13",
       caption="Data Source: StatsBomb") + 
  theme_minimal() +
  theme(
    plot.background = element_rect(fill='#021e3f', color='#021e3f'),
    panel.background = element_rect(fill='#021e3f', color='#021e3f'),
    plot.title = element_text(hjust=0.5, vjust=0, size=14),
    plot.subtitle = element_text(hjust=0.5, vjust=0, size=8),
    plot.caption = element_text(hjust=0.5),
    text = element_text(family="Geneva", color='white'),
    panel.grid = element_blank(),
    axis.title = element_blank(),
    axis.text = element_blank(),
    legend.position = "none"
  )

Мы меняем функцию geom_point на geom_density2d_filled, чтобы сгенерировать тепловую карту. Кроме того, мы добавляем функцию масштабирования, чтобы указать диапазон тепловой карты.

Вот результат кода:

Заключительные замечания

Отличная работа! Вы научились визуализировать футбольные данные с помощью R. Мы создали пасы, удары и тепловую карту давления.

Надеюсь, здесь вы сможете многому научиться. А также, пожалуйста, примените полученные знания к своим любимым командам.

Если вам интересна эта статья, загляните в мой профиль Medium, где вы найдете больше руководств по футбольной аналитике и обработке данных.

Спасибо, что прочитали мою статью!