R을 이용한 축구 데이터 분석 (MAP)
오늘 새벽 유럽 챔피언스 결승 경기로 많은 사람들이 아침잠을 설쳤을 것이다.
R을 이용하여 축구 데이터 분석을 할 수 있는 블로그를 발견하여 약간 변형하여 따라 해 보았다.
참조 블로그
https://towardsdatascience.com/how-to-visualize-football-data-using-r-ee963b3a0ba4
How to Visualize Football Data Using R
Tutorials on creating shots, passes, and heat maps
towardsdatascience.com
위 예시는 옛날 경기라 20/21 라리가의 메시를 중심으로 데이터 분석을 다시 진행하였다.
필요한 패키지 설치 및 라이브러리 불러오기
# 필요한 라이브러리 설치
install.packages('devtools')
devtools::install_github("statsbomb/SDMTools")
devtools::install_github("statsbomb/StatsBombR")
install.packages('tidyverse')
install.packages('ggsoccer' )
# 라이브러리 로드
library(tidyverse)
library(StatsBombR)
library(ggsoccer)
축구 오픈 데이터 깃허브 주소는 아래와 같다.
https://github.com/statsbomb/open-data
GitHub - statsbomb/open-data: Free football data from StatsBomb
Free football data from StatsBomb. Contribute to statsbomb/open-data development by creating an account on GitHub.
github.com
데이터 불러오기 (20/21년 스페인 라리가 바르셀로나와 셀타 비고 경기)
# 사용 가능한 모든 대회 검색
Comp <- FreeCompetitions()
# 대회 필터링
ucl_german <- Comp %>%
filter(competition_id==11 & season_name=="2020/2021")
# Retrieve all available matches
matches <- FreeMatches(ucl_german)
# Retrieve the event data
events_df <- get.matchFree(matches)
# 데이터 전처리
clean_df <- allclean(events_df)
메시의 패스 데이터 불러와서 시각화 하기
# 패스 맵
messi_pass <- clean_df %>%
filter(player.name == 'Lionel Andrés Messi Cuccittini') %>%
filter(type.name == 'Pass')
ggplot(messi_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="Lionel Andrés Messi's Passing Map",
subtitle="La Liga 20/21",
caption=" 데이터 소스: 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()
)
각 팀의 슛 맵을 그려보자
barcelona_shot <- clean_df %>%
filter(type.name == 'Shot') %>%
filter(team.name == 'Barcelona') %>%
select(player.name, location.x, location.y, shot.end_location.x, shot.end_location.y, shot.statsbomb_xg)
celta_shot <- clean_df %>%
filter(type.name == 'Shot') %>%
filter(team.name == 'Celta Vigo') %>%
select(player.name, location.x, location.y, shot.end_location.x, shot.end_location.y, shot.statsbomb_xg)
ggplot() +
annotate_pitch(dimensions = pitch_statsbomb, colour='white', fill='#021e3f') +
geom_point(data=barcelona_shot, aes(x=location.x, y=location.y, size=shot.statsbomb_xg) , color="red") +
geom_point(data=celta_shot, aes(x=120-location.x, y=location.y, size=shot.statsbomb_xg), color="yellow") +
labs( title= "Barcelona vs Celta Vigo",
subtitle = "Shots Map | La Liga 20/21",
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 map 그려보기
# Pressure Heat Map
barcelona_pressure <- clean_df %>%
filter(team.name == 'Barcelona') %>%
filter(type.name == 'Pressure')
ggplot(barcelona_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="Barcelona's Pressure Heat Map",
subtitle="La Liga 20/21",
caption=" 데이터 소스: 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"
)
앞으로 스포츠 데이터 분석 분야는 더 많은 수요가 있지 않을까?