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

Многие из тех, кто смотрит футбол и читает новости когда-нибудь видел метрику «xg». Что она вообще означает? Простыми словами Xg это количество ожидаемых голов. Т.е. каждый нанесённый удар по воротам имеет вероятность конвертироваться в забитый мяч, но с каждой позиции эта вероятность разная (если углубляться, то станет очевидным, что xg зависит от нескольких параметров, а не от одной позиции). К примеру, самая высокая вероятность забить мяч при исполнении пенальти. Чаще всего с пенальти дают 0.79 xg. Необходимо учитывать, что единой формулы расчёта xg нет, каждый провайдер рассчитывает её по-своему. Так например, для написания этой статьи я использовал данные с сайта https://understat.com/, но, если мы посмотрим другие источники, цифры будут отличаться.

Моя задача узнать, насколько точно Xg предсказывает количество голов в матче. Исследование будем проводить для АПЛ сезона 2022/2023. В данном исследовании мы ограничимся простыми методами анализа. Я составил таблицу из 380 матчей АПЛ. Пример таблицы с первыми 10 матчами АПЛ.

Table_EPL <- read.csv("F:\\EPL.csv")# Загружаем наш csv файл

Order – отвечает в таблице за количество матчей от 1 до 380

Week – в каком туре был сыгран матч, в Англии туры называют неделями. Предварительно для удобства все матчи объединены по турам, вне зависимости от даты, например матч 28 тура Брайтон – МЮ был сыгран 4 мая, хотя 28 тур игрался в середине марта.

Team1 – команда хозяин

Xg1 – показатель xg домашней команды

Goal1 – сколько голов забила домашняя команда

Goal2 – сколько голов забила гостевая команда

Xg2 – показатель xg гостевой команды

Team2 – команда гость

Изначальная таблица построена, далее будем считать разницу между забитыми мячами и xg у каждой из команд (diff1 и diff2), а потом напишем «yes» если разница меньше или равна 0.5, и, если разница строго больше 0.5 пишем «no» (Res1 и Res2).

Table_EPL$diff1 <- (Table_EPL$Xg1 - Table_EPL$Goal1)# Считаем разность Xg и забитых мячей для команд хозяев
Table_EPL$diff2 <- (Table_EPL$Xg2 - Table_EPL$Goal2)# Считаем разность Xg и забитых мячей для команд гостей
Table_EPL$Res1 <- ifelse(abs(Table_EPL$diff1) > 0.5, 'no', 'yes')# Условие "успешности" прдесказанных забитых голов для команд хозяев
Table_EPL$Res2 <- ifelse(abs(Table_EPL$diff2) > 0.5, 'no', 'yes')# Условие "успешности" прдесказанных забитых голов для команд гостей

Получится данная таблица:

Далее проведём два анализа строгий и нестрогий. В строгом анализе будем выводить «yes» если в Res1 и Res2 указано «yes», в нестрогом анализе если хотя бы в одном из столбцов имеется значение «yes».

Проведём строгий анализ

Table_EPL$success <- ifelse(Table_EPL$Res1 == 'yes' & Table_EPL$Res2 == 'yes', 'yes', 'no')# Условие "успешного" предсказания результата матча
Всего успешно предсказанных матчей получается 65, неуспешных соответственно 315.
Всего успешно предсказанных матчей получается 65, неуспешных соответственно 315.
length(which(Table_EPL$success == 'no' ))# Подсчёт "неуспешных" результатов

Теперь рассмотрим нестрогий анализ

Table_EPL$success <- ifelse(Table_EPL$Res1 == 'yes' | Table_EPL$Res2 == 'yes', 'yes', 'no')# Условие "успешного" предсказания результата матча

Получится таблица:

Всего успешно предсказанных матчей получается 241, неуспешных соответственно 139.
Всего успешно предсказанных матчей получается 241, неуспешных соответственно 139.
length(which(Table_EPL$success == 'no' ))# Подсчёт "неуспешных" результатов

Суммарные значения

sum(Table_EPL$Xg1,Table_EPL$Xg2)# Суммарный Xg
sum(Table_EPL$Goal1,Table_EPL$Goal2)# Суммарное количество голов

Суммарный xg равен 1136.54, мячей забито 1084, разница равна 52.54

Столь незначительное отклонение от забитых мячей говорит, что Xg может не быть точным в каждом конкретном матче, но на дистанции сезона, данная метрика покажет более чем хорошие результаты. Незначительное оно т.к. я рассматриваю ошибку предсказания в матче больше 0,5. В нашем случае разница значительно меньше 190(380 матчей * 0,5).

Далее приведу статистику средних значений.

Весь чемпионат:

summary(c(Table_EPL$Xg1,Table_EPL$Xg2))# Вычисляем средний Xg

Средний Xg – 1,48

summary(c(Table_EPL$Goal1,Table_EPL$Goal2))# Вычисляем среднее количество голов

Среднее кол-во голов – 1,43

Для команд хозяев:

summary(Table_EPL$Xg1)# Вычисляем средний Xg

Средний Xg – 1,67

summary(Table_EPL$Goal1)# Вычисляем среднее количество голов

Среднее кол-во голов – 1,63

Для команд гостей:

summary(Table_EPL$Xg2)# Вычисляем средний Xg

Средний Xg – 1,3

summary(Table_EPL$Goal2)# Вычисляем среднее количество голов

Среднее кол-во голов – 1,2

Ну и в конце проведём некую оценку точности показателей Xg. Я здесь имею ввиду, что чем больше забито мячей, тем большую неточность показывает Xg. Пример матч Ливерпуль 9:0 Борнмут, Xg в этом матче Ливерпуль 4,86 Борнмут 0,18.

Попробуем оценить в какой момент Xg не даёт удовлетворительную точность. Замечу, что здесь поменяем способ оценки и будем рассчитывать не интервал ± 0,5 xg, а значение xg большее или равное минимально допустимой границе для количества забитых мячей.

Для домашних игр:

length(which(Table_EPL$Goal1 == '4'))# Количество матчей с 4 голами
length(which(Table_EPL$Goal1 == '4' & Table_EPL$Xg1 >= '3.5'))# Количество матчей с 4 голами и Xg более 3.5

Матчей с 4 забитыми мячами – 28, xg ≥ 3,5 – 4 матча, точность ~ 14,3%

length(which(Table_EPL$Goal1 == '3'))# Количество матчей с 3 голами
length(which(Table_EPL$Goal1 == '3' & Table_EPL$Xg1 >= '2.5'))# Количество матчей с 3 голами и Xg более 2.5

Матчей с 3 забитыми мячами – 43, xg ≥ 2,5 – 19 матчей, точность ~ 44,2%

length(which(Table_EPL$Goal1 == '2'))# Количество матчей с 2 голами
length(which(Table_EPL$Goal1 == '2' & Table_EPL$Xg1 >= '1.5'))# Количество матчей с 2 голами и Xg более 1.5

Матчей с 2 забитыми мячами – 90, xg ≥ 1,5 – 53 матча, точность ~ 58,9% 

length(which(Table_EPL$Goal1 == '1'))# Количество матчей с 1 голом
length(which(Table_EPL$Goal1 == '1' & Table_EPL$Xg1 >= '0.5'))# Количество матчей с 1 голом и Xg более 0.5

Матчей с 1 забитым мячом – 124, xg ≥ 0,5 – 112 матчей, точность ~ 90,3% 

Построим простой график для иллюстрации

library(ggplot2)# Подключаем ggplot2 для построения графика
plot(Table_XG$week, Table_XG$Goal1, type =  "o", pch = 16,# Ось Х, Ось У, Тип линии графика, Тип точки на графике
     main = 'Xg in match',# Название графика
     xlab = 'week',# Подпись оси Х
     ylab = 'xg and goal',# Подпись оси У
     col = 'green3',# Цвет линии
     lwd = 2)# Толщина линии
xlines = seq(min(Table_XG$week), max(Table_XG$week), 1)# Создаём последовательность с указанием минимального и максимального значения
ylines = seq(min(Table_XG$Goal1), max(Table_XG$Goal1), 1)# Создаём последовательность с указанием минимального и максимального значения
abline(h = ylines, v = xlines, col = "lightgray")# Рисуем сетку по нашим последовательностям
lines(Table_XG$week, Table_XG$Xg1, type = "o", pch = 19, col = 'red', lwd = 2)# Добавляем вторую линию на график, аналогично первой
legend("topleft",# Создаём легенду и указываем её положение                                    
       legend = c("Goals", "Xg"),# Что будет указано в легенде
       col = c("green3", "red"),# указываем цвета в легенде
       lty = 7,# Тип линии в легенде
       pch = 19)# Тип точки в легенде

Для гостевых игр:

length(which(Table_EPL$Goal2 == '4'))# Количество матчей с 4 голами
length(which(Table_EPL$Goal2 == '4' & Table_EPL$Xg2 >= '3.5'))# Количество матчей с 4 голами и Xg более 3.5

Матчей с 4 забитыми мячами – 15, xg ≥ 3,5 – 2 матча, точность ~ 13,3% 

length(which(Table_EPL$Goal2 == '3'))# Количество матчей с 3 голами
length(which(Table_EPL$Goal2 == '3' & Table_EPL$Xg2 >= '2.5'))# Количество матчей с 3 голами и Xg более 2.5

Матчей с 3 забитыми мячами – 35, xg ≥ 2,5 – 7 матчей, точность ~ 20% 

length(which(Table_EPL$Goal2 == '2'))# Количество матчей с 2 голами
length(which(Table_EPL$Goal2 == '2' & Table_EPL$Xg2 >= '1.5'))# Количество матчей с 2 голами и Xg более 1.5

Матчей с 2 забитыми мячами – 76, xg ≥ 1,5 – 44 матча, точность ~ 57,9% 

length(which(Table_EPL$Goal2 == '1'))# Количество матчей с 1 голом
length(which(Table_EPL$Goal2 == '1' & Table_EPL$Xg2 >= '0.5'))# Количество матчей с 1 голом и Xg более 0.5

Матчей с 1 забитым мячом – 125, xg ≥ 0,5 – 112 матчей, точность ~ 89,6%

Построим простой график для иллюстрации

library(ggplot2)# Подключаем ggplot2 для построения графика
plot(Table_XG$week, Table_XG$Goal2, type =  "o", pch = 16,# Ось Х, Ось У, Тип линии графика, Тип точки на графике
     main = 'Xg in match',# Название графика
     xlab = 'week',# Подпись оси Х
     ylab = 'xg and goal',# Подпись оси У
     col = 'green3',# Цвет линии
     lwd = 2)# Толщина линии
xlines = seq(min(Table_XG$week), max(Table_XG$week), 1)# Создаём последовательность с указанием минимального и максимального значения
ylines = seq(min(Table_XG$Goal2), max(Table_XG$Goal2), 1)# Создаём последовательность с указанием минимального и максимального значения
abline(h = ylines, v = xlines, col = "lightgray")# Рисуем сетку по нашим последовательностям
lines(Table_XG$week, Table_XG$Xg2, type = "o", pch = 19, col = 'red', lwd = 2)# Добавляем вторую линию на график, аналогично первой
legend("topleft",# Создаём легенду и указываем её положение                                    
       legend = c("Goals", "Xg"),# Что будет указано в легенде
       col = c("green3", "red"),# указываем цвета в легенде
       lty = 7,# Тип линии в легенде
       pch = 19)# Тип точки в легенде

Выводы

Исходя из проведённого анализа можно сделать вывод, что xg показывает высокую точность предсказания результатов матчей на дистанции, а не в одном отдельном взятом матче. Это можно понять увидев, что при строгом анализе предсказано ~ 17,1% матчей, а при нестрогом ~ 63,4% матчей, что конечно хорошо, но как по мне недостаточно, учитывая, что мы считали матч успешным, если хотя бы у одной из команд предсказано значение. Также у Xg есть такой недостаток, как потеря точности при забитых мячах больше 2. В итоге можно сказать, что xg действительно хорошая и нужная метрика, однако она не является единственной главной.

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

Комментарии (6)


  1. nullslash
    07.11.2023 08:19

    Как мне кажется, у вас в тексте концептуальная ошибка. Значения xG присваиваются ударам после того, как матч был сыгран. По сути, вы анализируете, можно ли использовать xG, чтобы предсказать результат сыгранного матча.


    1. Dad0va Автор
      07.11.2023 08:19

      Отчасти соглашусь, но разъясню ход своих мыслей. Xg показывает сколько мы ожидаем голов в матче, грубо говоря предсказываем каким мог быть результат на основе ударов.


      1. tommyangelo27
        07.11.2023 08:19

        Это и так понятно, но XG в конкретном матче известен одновременно со счётом. Поэтому не годится для предсказания.

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

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

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


        1. Dad0va Автор
          07.11.2023 08:19

          Xg - количество ожидаемых голов в матче. В контексте этого термина ожидание и предсказание являются синонимами, и я говорю о том, что в отдельном взятом матче количество ожидаемых голов не всегда совпадает с реальным счётом, но на дистанции сезона эта статистика показывает хорошую точность.


          1. tommyangelo27
            07.11.2023 08:19

            В контексте этого термина ожидание и предсказание являются синонимами

            Ну хорошо, вот в субботу нас ждёт матч Вулверхемптона с Тоттенхемом. Вы в состоянии предсказать какими будут показатели XG у обеих команд?


            1. Dad0va Автор
              07.11.2023 08:19

              Метрика не подходит для предсказаний, её можно использовать для аналитики результата игры. В статье недочёт, что я некорректно использовал слово "предсказание"