e
Очень жаль, но панды не играют в футбол. Поэтому в этой статье речь пойдёт о возможностях библиотеки “Pandas”, название которой происходит от термина “panel data”. Сегодня мы расскажем, как с её помощью можно проанализировать статистику игр футбольных команд в Премьер-лиге.
Английская Премьер-лига — одно из самых обсуждаемых событий в футбольном мире. Фанаты делают предположения, а букмекерские конторы принимают ставки на то, кто же займёт призовые места. В этом сезоне чемпионом второй раз подряд стал "Манчестер Сити". Насколько вероятным такой исход является с точки зрения Data Science?
Исследователь Стивен Фордхэм (Stephen Fordham) из Борнмутского университета решил продемонстрировать, как можно использовать Python-библиотеку Pandas для анализа таблицы результатов футбольных клубов.
Для начала добудем саму таблицу с результатами. В Pandas есть встроенная функция read_html, которая использует библиотеки lxml и Beautiful Soup для автоматического сбора данных из HTML-файлов в виде объектов DataFrame. Установим несколько дополнительных модулей, введя в терминале команды:
pip install lxml
pip install beautifulsoup4 html5lib
Метод read_html имеет ряд настраиваемых параметров, но по умолчанию он пытается найти и проанализировать любые табличные данные в html-тегах <table>, собирая их в список DataFrame.
Далее импортируем библиотеку pandas и используем функцию read_html, чтобы проанализировать таблицу Премьер-лиги и присвоить её переменной prem_table. Так мы получим список, из которого возьмём первый элемент — он будет содержать в себе последние доступные результаты.
Поскольку основное внимание сосредоточено на гонке за 4 призовых места, мы отобразим 6 первых записей в таблице с помощью метода .head. Чтобы убедиться, что с данными всё в порядке, можно использовать атрибут shape. Он показывает размер таблицы, в нашем случае в ней 21 строка и 12 столбцов. Проверка оказалась полезной, так как Python начинает считать строки с индекса 0, а в Премьер-лиге всего 20 команд. Похоже, в нашей таблице есть лишние данные. Раз с первыми значениями всё хорошо, проблема должна быть в какой-то дополнительной строке в конце DataFrame.
import pandas as pd
prem_table = pd.read_html('https://www.bbc.co.uk/sport/football/premier-league/table')
Premier_table = prem_table[0]
print(len(prem_table))
print(type(prem_table))
print(Premier_table.head(6))
# Output
1
<class 'list'>
Перед тем как начать предварительный анализ, мы почистим данные. Столбец “Unnamed: 1” явно не несёт в себе полезной информации, поэтому удалим его с помощью метода drop с аргументом axis=1:
Premier_table.columns
Index(['Unnamed: 0', 'Unnamed: 1', 'Team', 'P', 'W', 'D', 'L', 'F', 'A', 'GD',
'Pts', 'Form'],
dtype='object')
Premier_league = Premier_table.drop(['Unnamed: 1'], axis=1)
Premier_league.head(6)
Результат:
Каждый столбец в DataFrame можно представить как Series, где должны быть только однотипные данные. Для дальнейшего анализа попробуем расшифровать тип каждой Series.
Взглянув на таблицу, можно сразу предположить, что столбец “Team” содержит в себе строки, а “P” (количество сыгранных игр) — целочисленные значения. Но лучше не доверять предположениям и использовать атрибут dtypes или метод info.
Видим, что все Series содержат в себе данные “object”, то есть строковые значения. Для выполнения численных расчётов нам необходимо преобразовать типы некоторых из них. В Python это тривиальная задача: мы просто используем метод pandas.to_numeric.
Изменим тип данных нескольких столбцов на float:
Вернёмся к нашим лишним строкам и посмотрим на три последних записи в DataFrame:
В последней строке содержатся ненужные метаданные. Чтобы удалить их, снова используем метод drop, но на этот раз без параметра axis=1 (поскольку обрабатываем строку, а не столбец). С помощью атрибута shape убедимся, что всё прошло успешно:
Table.drop(Table.tail(1).index, inplace=True)
Table.tail(3)
Table.shape
# Output
(20, 12)
Теперь посмотрим на столбец “Unnamed: 0”. Его название явно не согласуется с содержимым (с позицией команды в общем зачёте). Исправим это методом Pandas Dataframe.rename с аргументом Inplace=True, чтобы применить изменения к исходному DataFrame.
Table.columns
Index(['Unnamed: 0', 'Team', 'P', 'W', 'D', 'L', 'F', 'A', 'GD', 'Pts',
'Form'],
dtype='object')
Table.rename(columns={'Unnamed: 0':'Position'}, inplace=True)
Table.head()
Наш DataFrame теперь настроен. На этом этапе стоит попробовать создать несколько новых столбцов и проверить, будет ли для них работать преобразование строк в числа, сделанное нами ранее.
Сформируем столбец под названием «Соотношение голов» (“Goal Ratio”), показывающий отношение забитых мячей к пропущенным. Для этого нужно поделить столбец “F” на столбец “A” и округлить значения до одного знака после запятой. По умолчанию новые данные добавляются в конец DataFrame:
Чтобы переместить столбец, можно просто переопределить таблицу, указав нужный порядок:
Мы удалили столбец “Form”, чтобы данные выглядели более аккуратными.
Теперь наша таблица оформлена подобающим образом. Давайте начнём анализ с простого вопроса, например: «Какие команды сыграли на одну игру меньше своих соперников?». Так как все команды на момент написания статьи сыграли 34 или 35 игр, мы просто выводим те, у которых значение столбца “P” равно 34. Для фильтрации используем логическое индексирование:
Теперь давайте определим, у какой команды было больше всего результатов «ничья» (столбец “D”).
Клуб "Саутгемптон" изо всех сил пытается избежать вылета, повлияет ли это на их позицию?
Наконец, создадим ещё два столбца: число забитых и пропущенных голов за игру (“Goals/game” и “Goal conceded/game”). Отсортируем значения методом sort_values:
Table['Goals/game'] = round((Table.F / Table.P), 1)
Table['Goals conceded/game'] = round((Table['A'] / Table['P']), 1)
Table.sort_values(['Goals/game', 'Goal Ratio']).head(5)
После «Хаддерсфилда» и «Фулхэма» у клуба «Кардифф» третье худшее соотношение забитых и пропущенных голов. Смогут ли они продолжать бороться за более высокое место в таблице со своим ближайшим соперником, клубом «Брайтон»? Достаточное ли у них нападение, уязвима ли защита?
Мы можем выяснить это с помощью Pandas!
Что ж, похоже, их шансы невысоки.
Хотя английская Премьер-лига завершилась, в России она ещё продолжается — вы можете оценить статистику главных претендентов на первенство и предположить, кто же станет чемпионом. А если вы уже давно знакомы с анализом данных, то для больших вычислений рекомендуем воспользоваться нашими серверами с GPU NVIDIA Tesla V100.
Надеемся, что представленные в этой статье функции Pandas помогут вам в анализе данных. Напоследок один совет: не анализируйте статистику Премьер-лиги во время соревнований, поскольку пока вы пишете код, данные успеют поменяться. Все расчёты стоит выполнять после матчей. А пока — устраивайтесь поудобнее и наблюдайте за игрой!
С оригинальной статьёй можно ознакомиться на портале towardsdatascience.com.
С 1 июня ввозить товары из стран ЕАЭС на автомобилях возможно только по новым правилам,…
С 1 марта 2026 года начал действовать закон о русском языке, а точнее, вступили в…
Вы вложили деньги в сайт, наполнили его контентом, заказали рекламу, но клиенты всё равно уходят,…
Что такое корнер в торговле и бизнесе, зачем он нужен бренду, чем отличается от островка…
Что такое НТО, чем нестационарная торговая точка отличается от стационарной, какие требования действуют, где можно…
Разбираем, что такое контракт, чем он отличается от договора, в каких случаях его заключают и…