Учебники по созданию снимков, проходов и тепловых карт
Введение
Футбольная аналитика быстро развивалась в последние годы. С данными мы можем понять игру с другой точки зрения.
В этой статье я покажу вам, как визуализировать футбольные данные с помощью 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, где вы найдете больше руководств по футбольной аналитике и обработке данных.
Спасибо, что прочитали мою статью!