Як визначається переможець АПЛ

Футбол: Чому переможці перемагають, а невдахи програють

У цій статті ми вивчимо сучасні показники у футболі (xG, xGA та xPTS) та їх вплив у спортивній аналітиці.

  • Очікувані голи (xG) – вимірює якість пострілу на основі декількох змінних, таких як тип асисту, кут пострілу та відстань від воріт, чи це був удар головою та чи визначався він як великий шанс.
  • Очікувані гольові передачі (xGA) – вимірює ймовірність того, що даний пас стане гольовим. Він враховує кілька факторів, включаючи тип пасу, кінцеву точку пасу та його довжину.
  • Очікувані очки (xPTS) – вимірює ймовірність певної гри принести очки команді.

Ці показники дозволяють нам заглибитись у футбольну статистику та зрозуміти результати роботи гравців та команд загалом та усвідомити роль удачі та майстерності в ній. Спойлер: вони обидві важливі.

Процес збору даних для цієї статті описаний у цьому Kaggle kernel: Web Scraping Football Statistics

import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import collections import warnings from IPython.core.display import display, HTML # import plotly import plotly import plotly.figure_factory as ff import plotly.graph_objs as go import plotly.offline as py from plotly.offline import iplot, init_notebook_mode import plotly.tools as tls # configure things warnings.filterwarnings('ignore') pd.options.display.float_format = ' '.format pd.options.display.max_columns = 999 py.init_notebook_mode(connected=True) %load_ext autoreload %autoreload 2 %matplotlib inline sns.set() # !pip install plotly --upgrade

Імпорт даних та візуальний аналіз

df = pd.read_csv('../input/understat.com.csv') df = df.rename(index=int, columns=) df.head()

У наступній візуалізації ми перевіримо, скільки команд з кожної ліги були в топ-4 за останні 5 років. Це може дати нам деяку інформацію про стабільність найкращих команд з різних країн.

f = plt.figure(figsize=(25,12)) ax = f.add_subplot(2,3,1) plt.xticks(rotation=45) sns.barplot(x='team', y='pts', hue='year', data=df[(df['league'] == 'Bundesliga') & (df['position'] 

Як ми бачимо з цих гістологічних діаграм, є команди, які за останні 5 років були в топ-4 лише один раз, це означає, що це не є нормою для них, це означає, що якщо ми копнемо глибше, ми можемо виявити, що є фактор удачі, який можливо, зіграв на користь цим командам. Це просто теорія, тож давайте придивимось ближче до цих аномалій.

Команди, які потрапили у топ-4 лише один раз протягом останніх 5 сезонів:

  • Вольфсбург (2014) і Шальке 04 (2017) з Бундесліги
  • Лестер (2015) з Англійської Прем'єр Ліги
  • Вільяреал (2015) і Севілья (2016) з Іспанської Ла Ліги
  • Лаціо (2014) і Фіорентина (2014) з Італійської Серії А
  • Ліль (2018) і Сент-Етьєн (2018) з Французької Ліги 1
  • ФК Ростов (2015) і Динамо Москва (2014) з Російської Прем'єр Ліги

Давайте збережемо ці команди.

# Removing unnecessary for our analysis columns df_xg = df[['league', 'year', 'position', 'team', 'scored', 'xG', 'xG_diff', 'missed', 'xGA', 'xGA_diff', 'pts', 'xpts', 'xpts_diff']] outlier_teams = ['Wolfsburg', 'Schalke 04', 'Leicester', 'Villareal', 'Sevilla', 'Lazio', 'Fiorentina', 'Lille', 'Saint-Etienne', 'FC Rostov', 'Dinamo Moscow']
# Checking if getting the first place requires fenomenal execution first_place = df_xg[df_xg['position'] == 1] # Get list of leagues leagues = df['league'].drop_duplicates() leagues = leagues.tolist() # Get list of years years = df['year'].drop_duplicates() years = years.tolist()

Зрозуміти як переможці перемагають

У цьому розділі ми спробуємо знайти деякі шаблони, які можуть допомогти нам зрозуміти, якими є інгредієнти супу перемоги :D. Почнемо з Бундесліги.

Бундесліга

Дані в таблицях і заголовки в чартах англійською, тому що першоджерело зроблено цією мовою і змінювати все підряд забрало б занадто багато часу. Вибачаюсь 🙁

first_place[first_place['league'] == 'Bundesliga']
pts = go.Bar(x = years, y = first_place['pts'][first_place['league'] == 'Bundesliga'], name = 'PTS') xpts = go.Bar(x = years, y = first_place['xpts'][first_place['league'] == 'Bundesliga'], name = 'Expected PTS') data = [pts, xpts] layout = go.Layout( barmode='group', title="Comparing Actual and Expected Points for Winner Team in Bundesliga", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)

Подивившись на таблицю та діаграму, ми бачимо, що Баварія з кожним роком отримує більше очок, ніж вони повинні були отримати, вони забили більше голів, ніж очікувано, і пропустили менше, ніж очікувалося (за винятком 2018 року, який все-рівно не порушив їхнього плану виграти сезон, але це дає деякі підказки, що Баварія зіграла гірше цього року, хоча й конкуренти не скористалися цим).

# and from this table we see that Bayern dominates here totally, even when they do not play well df_xg[(df_xg['position'] 

Ла Ліга

first_place[first_place['league'] == 'La_liga']
pts = go.Bar(x = years, y = first_place['pts'][first_place['league'] == 'La_liga'], name = 'PTS') xpts = go.Bar(x = years, y = first_place['xpts'][first_place['league'] == 'La_liga'], name = 'Expected PTS') data = [pts, xpts] layout = go.Layout( barmode='group', title="Comparing Actual and Expected Points for Winner Team in La Liga", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)

Як ми бачимо з діаграми вище, що у 2014 та 2015 роках Барселона створювала достатньо моментів, щоб виграти титул і не покладатися на особисті навички чи удачу, з цих цифр насправді можна сказати, що справжня КОМАНДА грала в ті сезони.

У 2016 році між Мадридом та Барселоною було багато конкуренції, і врешті-решт Мадриду пощастило або королівський клуб мав більші яйця в одній конкретній грі (або Барселоні не пощастило / не показали яйця), і це стало ціною титулу. Я впевнений, що якщо копнути глибше цей сезон, ми зможемо знайти саме цей поєдинок.

У 2017 та 2018 роках успіх "Барселони" здебільшого заслуга діям Ліонеля Мессі, який забивав або робив гольові паси в ситуаціях, коли звичайні гравці цього б не робили. Що призвело до такого стрибка в різниці xPTS. І це змушує мене думати (маючи на увазі, що "Реал" в цьому сезоні дуже активний на трансферному ринку), що все може закінчитися погано. Просто суб'єктивна думка, заснована на числах та перегляді матчів Барселони. Дуже сподіваюся, що я помиляюся.

# comparing with runner-up df_xg[(df_xg['position'] 

АПЛ

first_place[first_place['league'] == 'EPL']
pts = go.Bar(x = years, y = first_place['pts'][first_place['league'] == 'EPL'], name = 'PTS') xpts = go.Bar(x = years, y = first_place['xpts'][first_place['league'] == 'EPL'], name = 'Expected PTS') data = [pts, xpts] layout = go.Layout( barmode='group', title="Comparing Actual and Expected Points for Winner Team in EPL", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)

У АПЛ ми бачимо чітку тенденцію, яка говорить вам: "Щоб перемогти, ти повинен бути кращим, ніж статистика". Цікавим випадком є історія Лестера при перемозі в 2015 році: вони отримали на 12 очок більше, ніж повинні були, і в той же час Арсенал недоотримав 6 очок! Ось чому ми любимо футбол, бо трапляються такі незрозумілі речі. Я не кажу, що це повністю удача, але вона зіграла тут значну роль.

Ще одна цікава річ - Манчестер Сіті 2018 року - вони супер стабільні! Вони забили лише на один гол більше, ніж очікувалося, пропустили на 2 менше і отримали 7 додаткових очок, в той час як Ліверпуль боровся дуже добре, мав трохи більше удачі на своєму боці, але не зміг перемогти, незважаючи на 13 очок випередження по xPTS.

Пеп закінчує будівництво машини знищення. Man City створює та конвертує свої моменти на основі майстерності та не покладається на удачу - це робить їх дуже небезпечними в наступному сезоні.

# comparing with runner-ups df_xg[(df_xg['position'] 

Ліга 1

first_place[first_place['league'] == 'Ligue_1']
pts = go.Bar(x = years, y = first_place['pts'][first_place['league'] == 'Ligue_1'], name = 'PTS') xpts = go.Bar(x = years, y = first_place['xpts'][first_place['league'] == 'Ligue_1'], name = 'Expected PTS') data = [pts, xpts] layout = go.Layout( barmode='group', title="Comparing Actual and Expected Points for Winner Team in Ligue 1", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)

У французькій Ligue 1 ми продовжуємо спостерігати тенденцію: "Щоб виграти, ти повинен виконати 110%, тому що 100% недостатньо". Тут Парі Сен Жермен повністю домінує. Тільки в 2016 році ми отримуємо виняток в особі Монако, який забив на 30 голів більше, ніж очікувалося. і отримав майже 17 балів більше, ніж очікувалося! Удача? Досить хороший шматок. ПСЖ був хороший в тому році, але Монако був надзвичайним. Знову ж таки, ми не можемо стверджувати, що це чиста удача чи чиста майстерність, а це ідеальне поєднання обох у потрібному місці в потрібний час.

# comparing with runner-ups df_xg[(df_xg['position'] 

Серія А

first_place[first_place['league'] == 'Serie_A']
pts = go.Bar(x = years, y = first_place['pts'][first_place['league'] == 'Serie_A'], name = 'PTS') xpts = go.Bar(x = years, y = first_place['xpts'][first_place['league'] == 'Serie_A'], name = 'Expecetd PTS') data = [pts, xpts] layout = go.Layout( barmode='group', title="Comparing Actual and Expected Points for Winner Team in Serie A", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)

В італійській Серії А "Ювентус" домінує 8 років поспіль, хоча не може досягти великих успіхів у Лізі чемпіонів. Я думаю, глянувши на цю діаграму та цифри, ми можемо зрозуміти, що Юве не має достатньо сильної конкуренції всередині країни і отримує багато "халявних" очок, що знову ж таки випливає з багатьох факторів, і ми можемо побачити, що Наполі в два рази випереджав "Ювентус" по показнику xPTS, але це справжнє життя, і, наприклад, 2017 року, Юве був божевільним і забив додаткові 26 голів (або створив голи з нізвідки), а Наполі пропустив на 3 більше, ніж очікувалося (через помилку воротаря чи, можливо, перевагу якоїсь команди в 1 або 2 конкретних спарингах). Як і у ситуації в Ла Лізі, коли Реал Мадрид став чемпіоном, я впевнений, що ми зможемо знайти 1 або 2 гри, які були ключовими в тому році.

Деталі мають значення у футболі. Розумієте, одна помилка тут, одна штанга там, і ви втратили звання чемпіона країни.

# comparing to runner-ups df_xg[(df_xg['position'] 

РФПЛ

first_place[first_place['league'] == 'RFPL']
pts = go.Bar(x = years, y = first_place['pts'][first_place['league'] == 'RFPL'], name = 'PTS') xpts = go.Bar(x = years, y = first_place['xpts'][first_place['league'] == 'RFPL'], name = 'Expected PTS') data = [pts, xpts] layout = go.Layout( barmode='group', title="Comparing Actual and Expected Points for Winner Team in RFPL", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)

Я не слідкую за російською Прем'єр-лігою, тому просто холодно дивлячись на дані, ми бачимо ту саму схему, - забивати більше, ніж ти заслуговуєш, а також цікава ситуація з московським ЦСКА з 2015 по 2017 рік. За ці роки ці хлопці були хороші, але конвертували свої переваги лише один раз, інші два - якщо ви не конвертуєте, вас карають, або ваш головний конкурент просто забиває більше.

У футболі немає справедливості :D. Хоча, я вважаю, що з VAR цифри стануть стабільнішими в наступні сезони. Тому що однією з причин цих додаткових голів та очок є помилки арбітрів.

# comparing to runner-ups df_xg[(df_xg['position'] 

Статистичний огляд

Оскільки є 6 ліг з різними командами та статистикою, я вирішив зосередитись на одній для початку, щоб перевірити різні підходи, а потім повторити остаточну модель аналізу на інші 5. І, оскільки я дивлюся переважно Ла Лігу, я почну з цього змагання,так як я знаю найбільше про нього.

# Creating separate DataFrames per each league laliga = df_xg[df_xg['league'] == 'La_liga'] laliga.reset_index(inplace=True) epl = df_xg[df_xg['league'] == 'EPL'] epl.reset_index(inplace=True) bundesliga = df_xg[df_xg['league'] == 'Bundesliga'] bundesliga.reset_index(inplace=True) seriea = df_xg[df_xg['league'] == 'Serie_A'] seriea.reset_index(inplace=True) ligue1 = df_xg[df_xg['league'] == 'Ligue_1'] ligue1.reset_index(inplace=True) rfpl = df_xg[df_xg['league'] == 'RFPL'] rfpl.reset_index(inplace=True)
def print_records_antirecords(df): print('Presenting some records and antirecords: n') for col in df.describe().columns: if col not in ['index', 'year', 'position']: team_min = df['team'].loc[df[col] == df.describe().loc['min',col]].values[0] year_min = df['year'].loc[df[col] == df.describe().loc['min',col]].values[0] team_max = df['team'].loc[df[col] == df.describe().loc['max',col]].values[0] year_max = df['year'].loc[df[col] == df.describe().loc['max',col]].values[0] val_min = df.describe().loc['min',col] val_max = df.describe().loc['max',col] print('The lowest value of had in and it is equal to '.format(col.upper(), team_min, year_min, val_min)) print('The highest value of had in and it is equal to '.format(col.upper(), team_max, year_max, val_max)) print('='*100) # replace laliga with any league you want print_records_antirecords(laliga)
Представлення деяких рекордів та антирекордів: Найнижчим значенням SCORED у Кордоби у 2014 році було 22,00 Найвищу цінність SCORED мав Реал Мадрид у 2014 році і він дорівнює 118,00 ===================================================== =============== Найменше значення XG було у Ейбара у 2014 році і воно дорівнює 29,56 Найвище значення XG мала Барселона у 2015 році і воно дорівнює 113,60 ===================================================== =============== Барселона у 2016 році мала найменше значення XG_DIFF і воно дорівнює -22,45 Найвище значення XG_DIFF мав Лас-Пальмас у 2017 році і воно дорівнює 13,88 ===================================================== =============== Найнижчий показник MISSED мав Atletico Madrid в 2015 році і він дорівнює 18.00 Найвище значення MISSED мала Осасуна в 2016 році і воно дорівнює 94,00 ===================================================== =============== Найменше значення XGA було в Atletico Madrid в 2015 році і воно дорівнює 27,80 Найвище значення XGA мав Levante у 2018 році і воно дорівнює 78,86 ===================================================== =============== Найнижчим значенням XGA_DIFF була Осасуна в 2016 році і вона дорівнює -29,18 Найвище значення XGA_DIFF мала Валенсія в 2015 році і воно дорівнює 13,69 ===================================================== =============== Найменше значення PTS було у Кордоби у 2014 році і воно дорівнює 20,00 Найвище значення PTS у Барселоні було у 2014 році і воно дорівнює 94,00 ===================================================== =============== Найнижче значення XPTS було в Гранаді в 2016 році і воно дорівнює 26,50 Найвище значення XPTS мали Барселона у 2015 році і воно дорівнює 94,38 ===================================================== =============== Найнижчий показник XPTS_DIFF мав Atletico Madrid в 2017 році і він дорівнює -17,40 Найвище значення XPTS_DIFF мали Deportivo La Coruna у 2017 році і воно дорівнює 20,16
trace0 = go.Scatter( x = laliga['position'][laliga['year'] == 2014], y = laliga['xG_diff'][laliga['year'] == 2014], name = '2014', mode = 'lines+markers' ) trace1 = go.Scatter( x = laliga['position'][laliga['year'] == 2015], y = laliga['xG_diff'][laliga['year'] == 2015], name='2015', mode = 'lines+markers' ) trace2 = go.Scatter( x = laliga['position'][laliga['year'] == 2016], y = laliga['xG_diff'][laliga['year'] == 2016], name='2016', mode = 'lines+markers' ) trace3 = go.Scatter( x = laliga['position'][laliga['year'] == 2017], y = laliga['xG_diff'][laliga['year'] == 2017], name='2017', mode = 'lines+markers' ) trace4 = go.Scatter( x = laliga['position'][laliga['year'] == 2018], y = laliga['xG_diff'][laliga['year'] == 2018], name='2018', mode = 'lines+markers' ) data = [trace0, trace1, trace2, trace3, trace4] layout = go.Layout( title="Comparing xG gap between positions", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)
trace0 = go.Scatter( x = laliga['position'][laliga['year'] == 2014], y = laliga['xGA_diff'][laliga['year'] == 2014], name = '2014', mode = 'lines+markers' ) trace1 = go.Scatter( x = laliga['position'][laliga['year'] == 2015], y = laliga['xGA_diff'][laliga['year'] == 2015], name='2015', mode = 'lines+markers' ) trace2 = go.Scatter( x = laliga['position'][laliga['year'] == 2016], y = laliga['xGA_diff'][laliga['year'] == 2016], name='2016', mode = 'lines+markers' ) trace3 = go.Scatter( x = laliga['position'][laliga['year'] == 2017], y = laliga['xGA_diff'][laliga['year'] == 2017], name='2017', mode = 'lines+markers' ) trace4 = go.Scatter( x = laliga['position'][laliga['year'] == 2018], y = laliga['xGA_diff'][laliga['year'] == 2018], name='2018', mode = 'lines+markers' ) data = [trace0, trace1, trace2, trace3, trace4] layout = go.Layout( title="Comparing xGA gap between positions", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)
trace0 = go.Scatter( x = laliga['position'][laliga['year'] == 2014], y = laliga['xpts_diff'][laliga['year'] == 2014], name = '2014', mode = 'lines+markers' ) trace1 = go.Scatter( x = laliga['position'][laliga['year'] == 2015], y = laliga['xpts_diff'][laliga['year'] == 2015], name='2015', mode = 'lines+markers' ) trace2 = go.Scatter( x = laliga['position'][laliga['year'] == 2016], y = laliga['xpts_diff'][laliga['year'] == 2016], name='2016', mode = 'lines+markers' ) trace3 = go.Scatter( x = laliga['position'][laliga['year'] == 2017], y = laliga['xpts_diff'][laliga['year'] == 2017], name='2017', mode = 'lines+markers' ) trace4 = go.Scatter( x = laliga['position'][laliga['year'] == 2018], y = laliga['xpts_diff'][laliga['year'] == 2018], name='2018', mode = 'lines+markers' ) data = [trace0, trace1, trace2, trace3, trace4] layout = go.Layout( title="Comparing xPTS gap between positions", xaxis=, yaxis= ) fig = go.Figure(data=data, layout=layout) py.iplot(fig)

З наведених вище діаграм видно, що найкращі команди забивають більше, пропускають менше та отримують більше очок, ніж очікувалося. Тому ці команди - топ-команди. І зовсім протилежна ситуація з аутсайдерами. Команди середнього рівня середні. Цілком логічно, тут немає неймовірних знахідок.

# Check mean differences def get_diff_means(df): dm = df.groupby('year')[['xG_diff', 'xGA_diff', 'xpts_diff']].mean() return dm means = get_diff_means(laliga) means
# Check median differences def get_diff_medians(df): dm = df.groupby('year')[['xG_diff', 'xGA_diff', 'xpts_diff']].median() return dm medians = get_diff_medians(laliga) medians

Виявлення винятків

Z-Score

Z-Score - кількість стандартних відхилень від середньої точки даних. Ми можемо використовувати його для пошуку інших винятків у нашому наборі даних, вважаючи, що | z-оцінка | > 3 - виняток.

# Getting outliers for xG using zscore from scipy.stats import zscore # laliga[(np.abs(zscore(laliga[['xG_diff']])) > 2.0).all(axis=1)] df_xg[(np.abs(zscore(df_xg[['xG_diff']])) > 3.0).all(axis=1)]
# outliers for xGA # laliga[(np.abs(zscore(laliga[['xGA_diff']])) > 2.0).all(axis=1)] df_xg[(np.abs(zscore(df_xg[['xGA_diff']])) > 3.0).all(axis=1)]
# Outliers for xPTS # laliga[(np.abs(zscore(laliga[['xpts_diff']])) > 2.0).all(axis=1)] df_xg[(np.abs(zscore(df_xg[['xpts_diff']])) > 3.0).all(axis=1)]

Всього виявлено 12 винятків. Бідна Осасуна в 2016 році - майже 30 незаслужених голів.

Як ми бачимо з цих даних, перебування в просторі винятків, ще не робить вас переможцем сезону. Але якщо ви втрачаєте свої можливості або пропускаєте голи там, де не слід, і робите це занадто часто - ви заслуговуєте на виліт. Програвати і бути середнім набагато простіше, ніж вигравати.

Міжквартильний діапазон (IQR)

IQR - різниця між першим кварталом і третім кварталом набору даних. Це один із способів описати поширення набору даних.

Загальновживане правило говорить, що точка даних є винятком, якщо вона більше 1,5 ⋅ IQR третього кварталу або на стільки ж нижче першого кварталу. Іншими словами, низькі винятки є нижчими за Q1 - 1,5 ⋅ IQR, а високі - понад Q3 + 1,5 ⋅ IQR.

# Trying different method of outliers detection df_xg.describe()
# using Interquartile Range Method to identify outliers # xG_diff iqr_xG = (df_xg.describe().loc['75%','xG_diff'] - df_xg.describe().loc['25%','xG_diff']) * 1.5 upper_xG = df_xg.describe().loc['75%','xG_diff'] + iqr_xG lower_xG = df_xg.describe().loc['25%','xG_diff'] - iqr_xG print('IQR for xG_diff: '.format(iqr_xG)) print('Upper border for xG_diff: '.format(upper_xG)) print('Lower border for xG_diff: '.format(lower_xG)) outliers_xG = df_xg[(df_xg['xG_diff'] > upper_xG) | (df_xg['xG_diff'] < lower_xG)] print('='*50) # xGA_diff iqr_xGA = (df_xg.describe().loc['75%','xGA_diff'] - df_xg.describe().loc['25%','xGA_diff']) * 1.5 upper_xGA = df_xg.describe().loc['75%','xGA_diff'] + iqr_xGA lower_xGA = df_xg.describe().loc['25%','xGA_diff'] - iqr_xGA print('IQR for xGA_diff: '.format(iqr_xGA)) print('Upper border for xGA_diff: '.format(upper_xGA)) print('Lower border for xGA_diff: '.format(lower_xGA)) outliers_xGA = df_xg[(df_xg['xGA_diff'] > upper_xGA) | (df_xg['xGA_diff'] < lower_xGA)] print('='*50) # xpts_diff iqr_xpts = (df_xg.describe().loc['75%','xpts_diff'] - df_xg.describe().loc['25%','xpts_diff']) * 1.5 upper_xpts = df_xg.describe().loc['75%','xpts_diff'] + iqr_xpts lower_xpts = df_xg.describe().loc['25%','xpts_diff'] - iqr_xpts print('IQR for xPTS_diff: '.format(iqr_xpts)) print('Upper border for xPTS_diff: '.format(upper_xpts)) print('Lower border for xPTS_diff: '.format(lower_xpts)) outliers_xpts = df_xg[(df_xg['xpts_diff'] > upper_xpts) | (df_xg['xpts_diff'] < lower_xpts)] print('='*50) outliers_full = pd.concat([outliers_xG, outliers_xGA, outliers_xpts]) outliers_full = outliers_full.drop_duplicates()
IQR для xG_diff: 13.16 Верхня границя для xG_diff: 16.65 Нижня границя для xG_diff: -18.43 ================================================== IQR для xGA_diff: 13.95 Верхня границя для xGA_diff: 17.15 Нижня границя для xGA_diff: -20.05 ================================================== IQR для xPTS_diff: 13.93 Верхня границя для xPTS_diff: 18.73 Нижня границя для xPTS_diff: -18.41 ==================================================
# Adding ratings bottom to up to find looser in each league (different amount of teams in every league so I can't do just n-20) max_position = df_xg.groupby('league')['position'].max() df_xg['position_reverse'] = np.nan outliers_full['position_reverse'] = np.nan for i, row in df_xg.iterrows(): df_xg.at[i, 'position_reverse'] = np.abs(row['position'] - max_position[row['league']])+1 for i, row in outliers_full.iterrows(): outliers_full.at[i, 'position_reverse'] = np.abs(row['position'] - max_position[row['league']])+1
total_count = df_xg[(df_xg['position'] '.format(outlier_prob))
Ймовірність винятку в верхній чи нижній частині фінальної таблиці: 8.10%

Тож можна сказати, що дуже ймовірно, що щороку в одній із 6 ліг буде команда, яка отримує путівку до Ліги чемпіонів чи Ліги Європи за допомогою удачі, окрім своїх чудових навичок, або є невдаха, яка падає до другого дивізіону, оскільки вони не можуть конвертувати свої моменти.

# 1-3 outliers among all leagues in a year data = pd.DataFrame(outliers_full.groupby('league')['year'].count()).reset_index() data = data.rename(index=int, columns=) sns.barplot(x='league', y='outliers', data=data) # no outliers in Bundesliga

Наші переможці та переможені з блискучими даними та не дуже.

top_bottom = outliers_full[(outliers_full['position'] 
# Let's get back to our list of teams that suddenly got into top. Was that because of unbeliavable mix of luck and skill? ot = [x for x in outlier_teams if x in top_bottom['team'].drop_duplicates().tolist()] ot # The answer is absolutely no. They just played well during 1 season. Sometimes that happen.

Висновки

Футбол - це гра з низьким рівнем балів, і один гол може змінити всю картину гри і навіть кінцеві результати. Ось чому довгостроковий аналіз дає нам кращу картину ситуації.

З впровадженням метрики xG (та інших, що випливають з нього) тепер ми можемо реально оцінити результати роботи команди в довгостроковій перспективі і зрозуміти різницю між топ-командами, командами середнього класу та абсолютними аутсайдерами.

xG вводить нові аргументи в дискусії навколо футболу, що робить його ще цікавішим. І в той же час гра не втрачає цей фактор невизначеності та можливості божевільних речей. Насправді зараз ці шалені речі мають шанс бути поясненими.

Врешті-решт ми виявили, що майже в 100% шанси в одній з ліг трапиться щось дивне. Це лише питання часу, наскільки епічним це буде.

Оригінальна робота з інтерактивними графіками може бути знайдена тут.

Неймовірний чемпіон, обмін гравцями та потужне представництво у Європі. Що чекати від нового сезону АПЛ?

Вже за півтора тижні стартує новий розіграш Англійської Прем’єр-ліги. Інформатор починає серію матеріалів, в яких розкажемо - чого чекати у цих сезонах фанатам топ-ліг. Починаємо з найпопулярнішого та найближчого за часом чемпіонату - АПЛ.

Перед сезоном

Огляд АПЛ почнемо із вартості. Тут маємо цікаву історію: вперше за довгий час чемпіон Англії, переможець Ліги Чемпіонів та тріумфатор Кубку Манчестер Сіті - не найдорожча команда ліги. За оцінками Transfermarkt, уперед вирвався Арсенал - 1,21 млрд проти 1,16 млрд євро на сьогодні. У цьому рейтингу вся велика шістка на своїх місцях: далі йде Челсі (880), МЮ (847), Ліверпуль (796) та Тоттенгем (773).

Найближче за вартістю підібралася Астон Вілла - 588 мільйонів. Саме її називають сірим кардиналом цього сезону. Команда у міжсезоння підсилилася: безкоштовно прийшов один з найкращих гравців Лестера Тілеманс, сумарно 88 млн віддали за Діабі та Пау Торреса. Ходять чутки, що ще один Торрес може з’явитися у складі - вінгер Барселони. Феррана Торреса команда готова взяти в оренду із правом подальшого викупу, а угода майже досягнута.

Та й подивіться, що вони виробляють. Основний захисник, 25-річний Конса протягнув м’яча через все поле у грі проти Брентфорда та ефектно завершив у верхній кут. Атакувальні захисники - не новинка для АПЛ, але таким проходом команда показує, що готова розривати всіх у боротьбі за вищі щаблі.

Stop what you're doing and watch this. 👀

І трохи про новачків. Бернлі, переможець Чемпіоншипу, влаштовує собі від сезону в сезон справжні гойдалки. Ще кілька років тому команда грала у ЛЄ, потім вилетіла з вищого дивізіону - і знову у нього повернулася. Із помітного - придбали переможця молодіжного євро Траффорда. Добре знайомий Шеффілд знову в еліті. Так само, полюбляє змінювати прописку з року в рік. Ну і всі ми слідкуємо за Лутоном. Команда з мемним стадіоном драматично вийшла у перший для себе сезон АПЛ - і саме за них будуть таємно вболівати фанати у матчах проти грандів.

Перший ігровий день нового сезону АПЛ - п’ятниця, 11.08. Гратиме Бернлі проти Манчестер Сіті. На той же уік-енд заплановано і всі інші матчі першого туру.

Потенційно новий чемпіон?

Пам’ятаєте, як минулого сезону всі казали, що нарешті в Англії буде новий чемпіон? Але, Арсенал не витримав шаленого тиску наприкінці сезону, а Манчестер Сіті вже у звичній для себе манері відпустив суперника вперед, дав насолодитися тимчасовим успіхом, потім видав серію перемог і обійшов лондонців. Традиційний багаторічний розклад: Сіті чемпіон, а якась команда в останню мить втрачає всі шанси на золото.

Та всі аналітики (і ми також) запевняють, що цьогорічна боротьба за тріумф в АПЛ буде дуже спекотною. Арсенал не гребує розкидатися грошима за футболістів. Придбали Райса, Хаверца та Тімбера. Артета, вивчивши досвід минулого сезону, готує глибший склад на всі позиції, адже у грі на виживання проти містян треба мати запас міцності. Саме цього канонірам не вистачило у 23-му році.

А що там Зінченко? Чутки про його травму чи нетравму ходять давно і прокоментувати їх чітко поки ніхто не брався. Днями Артета сказав, що в українця була невелика проблема з м'язами, через що той не брав участь у турне лондонців. Але Зінченко має скоро повернутися. Попереду - новий потенційно чемпіонський сезон. А також - Game4Ukraine із Шевченком та зірковою класикою нульових.

Переможець АПЛ Манчестер Сіті у міжсезоння провів поки одну закупівлю: у Челсі взяли Матео Ковачича. Той майже одразу заявив, що “містяни” - це новий рівень.

"Я тут лише два тижні, але одразу видно, що Гвардіола має чіткі уявлення про те, що він шукає. Він може навчити мене як краще рухатися. Для цього я приїхав сюди. Щоб навчитися бути найкращою версією себе", - заявив Матео.

Втрат у команди більше: продали в СА Мареза, безкоштовно пішов Гюндоган. Але, в атаці у Сіті ніколи не буде проблем: знайдуться ті, хто буде забивати у будь-якій ситуації.

Перша перевірка сил буде вже у неділю: матч Суперкубку Англії між Манчестер Сіті та Арсеналом. Відчуваєте, скільки лоску у цьому анонсі?

Хто не буде претендувати на золото? Все ще не готовий до цього Ліверпуль - ми так і не побачили у міжсезоння, що кризу подолано. Клопп залишився і його головна задача - перебудова. Тим паче трансферна активність команди була в обидва боки, але про це трохи нижче. Челсі, звісно, чимало зробив за час літньої паузи та навіть виграв товариський турнір команд еліти. Мудрик запалив своє ім’я серед аристократів і про нього знову говорять як про надію на новий сезон. Проте ми поки не віримо, що команда здатна претендувати на медалі. Навколо Тоттенгема багато чуток, що Кейн нарешті може підняти над головою кубок Ліги. Щоправда, у футболці Баварії, а не лондонців. А МЮ, вигравши бронзу, намагається владнати внутрішні чвари. Ну і поки мало видається, що хтось ще з інших команд ліги готовий на щось більше, аніж штурмувати зону ЛЧ.

Цікаво буде спостерігати за Ньюкаслом та Астон Віллою. Обидві команди мають високі задачі на сезон, обидві гратимуть в єврокубках. Обидві вивчили уроки надмірного тиску та інтенсивної гри на дистанції і як це може нашкодити. Здається, саме вони будуть головними загадками поза межами Топ-6. До речі, в Англії найширше представництво в Європі - аж вісім команд. Додався Вест Гем, який виграв ЛК.

Трансферна активність

І коротенько про трансфери. В очі кидається те, що топ-клуби більше полювали на гравців всередині, аніж поза межами ліги. Райс, Хаверц, Ковачич - найбагатші клуби вирішили взяти собі вже перевірених часом гравців та тих, хто розуміється на внутрішній кухні Англії. З-за кордону прийшли Собослаі, Онана, Тоналі, Порро і Кулушевскі. Ну і Челсі шукав топові підписання не в Англії. Поза межами острова угоди укладали, переважно, середняки. Англія збирає цьогорічні трансферні рекорди. Ліга витратила більше всіх - більше мільярда, перевага за цифрами майже втричі. Доклався до цього Арсенал (витрачено понад 230 мільйонів, найбільше у світі).

В інший бік - АПЛ стала однією з головних жертв пограбунку європейського футболу саудитами. Пішли Фабіньо, Кулібалі, Сен-Максімен, Менді, Марез, Канте, Фірміно, Теллес, Невеш… Ви теж вже бачите тут топову команду лише з екс-гравців Англійської ліги? І це ми ще поверхнево пройшлися. Цікаво, що суми компенсацій не такі вже й великі, як можна було очікувати від саудитів: лише 23 мільйони за Кулібалі, трохи більше 40 за Фабіньо. А Фірміно Аль-Ахлі взагалі запросив як вільного агента. Серед гучних трансферів не у СА - перехід Мойзе Кіна з Евертона в Ювентус за 30 млн, Пулішич у Мілан за 20 та Джака у Байер за 15.

Підсумуємо все викладене. За перемогу в АПЛ боротимуться щонайменше чотири команди, і дві з них - не топові представники. Трансферна епопея триває - але більшість гравців поповнюють лави саудівських клубів, аніж європейських грандів. Всередині АПЛ набагато більше гучних та дороговартісних переходів. А ледь не половина її команд будуть вирішувати ще й єврокубкові задачі. Словом, цього року говорити про Англію ми будемо в рази більше. Ну а незабаром чекайте анонс іспанської Ла Ліги, яка також стартує вже через вікенд.

Артем Россінський, для Інформатора

Підписуйтесь на наш Telegram-канал, щоб не пропустити важливих новин. За новинами в режимі онлайн прямо в месенджері слідкуйте на нашому Telegram-каналі Інформатор Live. Підписатися на канал у Viber можна тут.

Related Post

Чи можна їсти мед на ніч під час схудненняЧи можна їсти мед на ніч під час схуднення

Ніч — час, коли в організмі активізуються процеси спалювання жиру. Мед, завдяки своїй здатності прискорювати обмін речовин, може посилити ці процеси. Вживання меду на ніч сприяє більш ефективному спалюванню жирів

Якою стороною кріпити пароізоляцію BЯкою стороною кріпити пароізоляцію B

Вибирати краще односторонній ламінований матеріал, що укладається гладкою стороною в напрямку утеплювача. Металізована плівка. Металізованою стороною її монтують до пароізоляції. Паробар`єр стелиться будь-якою стороною, якщо вони однакові. Якщо один з

Яку дію має ТраумельЯку дію має Траумель

Зміст:1 Траумель С розчин для ін’єкцій (Traumeel ® S) Лікарські препарати1.1 Показання Траумель С розчин для ін єкцій1.2 Застосування Траумель С розчин для ін єкцій1.3 Протипоказання1.4 Побічна дія1.5 Особливості застосування1.6