Как получить доступ к API-интерфейсу Fantasy Premier League, создать фрейм данных и провести анализ с помощью Jupyter, Python и Pandas

Документация по созданию фрейма данных Pandas из FPL API и проведения анализа стоимости в сезоне 19/20.

На момент написания этого руководства перед 30+ неделями матчей я занимал 3919 место в мире в Fantasy Premier League Soccer (команда: Yin Aubameyang), что соответствует 0,05% лучших в мире.

Это произошло не случайно, и это была не вся удача.

Потребовалось несколько лет игры в эту игру, чтобы научиться терпению, навыкам и стратегии, необходимым для успеха. С № 1,181,262 в 2011/12 г. по № 39,804 в 2018/19 г., а теперь № 3,919 в 2019/20 г., когда осталось 8 GW:

За эти несколько лет я усвоил два действительно полезных навыка:

  1. Выявление ваших предубеждений
  2. Понимание того, как читать данные

Первое поможет вам перестать совершать глупые ошибки. Второй поможет вам раскрыть ценность, которой не хватает другим фэнтезийным менеджерам.

Это руководство поможет развить эти 2 навыка, научив вас получать доступ к новым данным. А затем помочь вам взглянуть на это по-новому.

Этот документ далек от совершенства, но, по крайней мере, он даст вам представление о том, что возможно с Jupyter Notebooks, Pandas, Python и новым источником данных.

К концу этого руководства у вас будут базовые навыки извлечения данных из Fantasy Premier League API и работы с данными, чтобы получить новое понимание.

Давайте погрузимся.

Примечание автора: для следующего испытания FPL API добавьте в закладки мой блог здесь, в разделе "Цикл через конечную точку" Element-Summary "FPL API:



Прохождение через конечную точку« Element-Summary API Fantasy Premier League для загрузки игрока…
Документация для создания Master DataFrame всех историй игровых недель игроков за текущий сезон и всех Прошлое… todatascience.com »



Оглавление:

  1. "Начиная"
  2. Доступ к API с запросами
  3. Создайте DataFrame из ответа на ваш запрос API
  4. Работа с Dataframe
  5. Экспорт в CSV для анализа в Google Таблицах или Excel (если это вам нравится)

Шаг 1. Начало работы

В этом руководстве предполагается, что вы немного знакомы с Jupyter и Python. Если вы только начинаете, начните с моего руководства здесь:



После завершения настройки возвращайтесь к этой статье!

Если у вас уже установлены Jupyter, Python и Pandas, переходите к шагу 2!

Шаг 2. Доступ к API с помощью запросов

Во-первых, нам понадобится импорт нашего пакета. Нам действительно нужно всего 3:

import requests
import pandas as pd
import numpy as np

Примечание. Если вы получили сообщение об ошибке импорта, вероятно, вы не добавили пакет в свою среду или не активировали среду разработки. Перейдите в свой Anaconda Navigator и обязательно добавьте пакет, необходимый в любую среду, которую вы активируете для работы с Jupyter Notebook. Примените обновление и не забудьте перезапустить терминал перед активацией среды разработки!

Далее нам понадобится URL API:

url = 'https://fantasy.premierleague.com/api/bootstrap-static/'

Используйте пакет запросов, чтобы сделать запрос GET от конечной точки API:

r = requests.get(url)

Затем преобразуйте этот запрос в объект json:

json = r.json()

Давайте посмотрим на ключи json, а затем мы создадим наши фреймы данных.

json.keys()

Это возвращает список всех ключей к json:

Три ключа, которые меня действительно интересуют в этой статье, - это elements, element_type и teams.

Затем мы создадим три разных фрейма данных, используя эти три ключа, а затем сопоставим некоторые столбцы из teams и element_type фреймов данных в наш elements фрейм данных.

Шаг 3. Создайте DataFrame из ответа на запрос API.

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

Итак, давайте начнем с создания наших фреймов данных:

elements_df = pd.DataFrame(json['elements'])
elements_types_df = pd.DataFrame(json['element_types'])
teams_df = pd.DataFrame(json['teams'])

Предварительно просмотрите 5 верхних строк ваших фреймов данных с помощью метода head(). Вот так:

elements_df.head()

Вы также можете получить представление обо всех столбцах в каждом фрейме данных с помощью метода columns:

elements_df.columns

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

slim_elements_df = elements_df[['second_name','team','element_type','selected_by_percent','now_cost','minutes','transfers_in','value_season','total_points']]

Теперь большинство данных, которые меня интересуют, можно просмотреть в одном окне:

slim_elements_df.head()

Успех! Давайте двигаться дальше.

Шаг 4: Работа с фреймом данных

Этот раздел будет разбит на подразделы:

Использование Map ()

Первое, что я собираюсь сделать, это сопоставить название позиции с elements_type_df на slim_elements_df. Если вы когда-либо использовали Excel, вы заметите, что map() очень похож на v-lookup.

slim_elements_df['position'] = slim_elements_df.element_type.map(elements_types_df.set_index('id').singular_name)

Теперь, когда мы это сделали, взглянем на несколько верхних строк:

slim_elements_df.head()

Отлично, теперь мы можем легко увидеть позицию. Это пригодится, когда мы организуем value_season по позициям.

Затем давайте добавим название команды. Мы можем сделать это, сопоставив «name» из нашего team_df:

slim_elements_df['team'] = slim_elements_df.team.map(teams_df.set_index('id').name)

Вуаля:

Затем отсортируем эту таблицу по value_season. Мне любопытно взглянуть на самые выгодные варианты в этом году.

Использование astype ()

НО ПЕРВЫЙ, мы должны создать новый столбец с именем value.

Почему? Поскольку некоторые значения в столбце value_season являются строковыми значениями. Я знаю это, потому что попытался отсортировать по value_season и получил странный неправильный результат. Необъяснимое поведение в вашем фрейме данных часто может быть связано с конфликтующими типами данных, хранящихся в одном столбце (например: строки, целые числа и значения с плавающей запятой, все хранятся в одном столбце).

Нам нужно убедиться, что каждое значение имеет один и тот же тип. Для этого мы создадим новый столбец и воспользуемся методом astype(), чтобы установить для всех значений значение с плавающей запятой (причудливый разговор для чисел с десятичными знаками, например: 4.5).

slim_elements_df['value'] = slim_elements_df.value_season.astype(float)

Теперь мы можем отсортировать наш фрейм данных по столбцу value. Давай сделаем это:

Использование sort_values ​​()

Sort_values ​​() позволяет вам сортировать значения :)

По умолчанию Pandas сортирует значения по возрастанию от меньшего к большему. Но мы хотим, чтобы значения отсортировывались по убыванию: от большего к меньшему. Поэтому нам нужно явно установить для параметра ascending значение False, например:

slim_elements_df.sort_values('value',ascending=False).head(10)

Хорошо, ты посмотришь на это? Два игрока заняли первое место. Поуп и Лундстрам. Вратарь и защитник. Отлично.

По сути, это означает, что Поуп и Лундстрам заработали наибольшее количество баллов за каждую стоимость, потому что значение рассчитывается просто путем деления total_points на now_cost.

значение = баллы / стоимость

Вы ожидали, что это будет так? Защитник и вратарь? Может ли это изменить ваше отношение к подбору команд в следующем году? Или на следующей неделе?

Использование pivot_table ()

Затем мы создадим сводную_таблицу в столбце position и посмотрим на значение за позицией:

slim_elements_df.pivot_table(index='position',values='value',aggfunc=np.mean).reset_index()

После создания сводной_таблицы и назначения сводной_таблицы переменной pivot мы отсортируем сводную таблицу по убыванию по значению:

pivot=slim_elements_df.pivot_table(index='position',values='value',aggfunc=np.mean).reset_index()
pivot.sort_values('value',ascending=False)

Это дает нам:

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

Чтобы решить эту проблему, давайте удалим из нашего фрейма данных всех игроков, у которых в этом сезоне нет минут. Мы будем использовать loc[] впервые:

Использование .loc []

.loc позволяет вам находить определенные строки с определенными значениями столбцов. Это похоже на фильтрацию электронной таблицы по определенному значению в столбце.

Для наших текущих целей мы хотим найти все строки в нашем фрейме данных, которые имеют значение больше нуля, чтобы удалить все значения = 0. Мы делаем это не только для хранителей. Нам нужно сделать это для каждой позиции. Мы пишем:

slim_elements_df = slim_elements_df.loc[slim_elements_df.value > 0]

Теперь давайте снова запустим эту сводную таблицу:

pivot = slim_elements_df.pivot_table(index='position',values='value',aggfunc=np.mean).reset_index()

а потом:

pivot.sort_values('value',ascending=False)

Вот и все:

Теперь давайте создадим сводную таблицу другого типа. На этот раз мы посмотрим, какие команды приносят наибольшую пользу в этом году. Единственное, что нужно изменить в этом операторе pivot_table, - это индекс и переменная pivot_table. Взглянем:

team_pivot = slim_elements_df.pivot_table(index='team',values='value',aggfunc=np.mean).reset_index()

Теперь мы отобразим team_pivot в отсортированном порядке, от самой ценной команды к самой низкой:

team_pivot.sort_values('value',ascending=False)

Результаты следующие:

Поклонникам волков не нужно беспокоиться о своих врожденных предубеждениях. Счастливчик!

С другой стороны, болельщики «шпор» должны были более осознанно относиться к своей команде, чтобы добиться успеха в ФПЛ в этом году. Как напряженно.

Использование .hist ()

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

fwd_df = slim_elements_df.loc[slim_elements_df.position == 'Forward']
mid_df = slim_elements_df.loc[slim_elements_df.position == 'Midfielder']
def_df = slim_elements_df.loc[slim_elements_df.position == 'Defender']
goal_df = slim_elements_df.loc[slim_elements_df.position == 'Goalkeeper']

Затем мы воспользуемся .hist() методом в нашем goal_df.value столбце фрейма данных:

goal_df.value.hist()

Это дает нам:

Здесь приличное значение выше 20. Давайте посмотрим на наш фрейм данных, отсортированный по значению, чтобы увидеть, что это за символы:

goal_df.sort_values('value',ascending=False).head(10)

Забрать? Позиция вратаря очень ценна.

Есть множество других способов нарезать этот сыр, но давайте перейдем к гистограммам позиции защитника:

def_df.value.hist()

Наша защитная гистограмма указывает на кое-что интересное. Заметили разницу между гистограммой вратаря и гистограммой защитника?

Для вратаря есть «лучший» выбор, но мы действительно не знаем, кто он будет начинать сезон. Оказывается, выбор вратаря был довольно прощающим, учитывая, сколько вратарей предлагали значение от 20 до 26:

У защитников, с другой стороны, был только один явный победитель в этом году и лишь несколько других в диапазоне значений 20–25, которые выделялись из общей массы. Давайте посмотрим на верхнюю часть таблицы значений защитника:

def_df.sort_values('value',ascending=False).head(10)

Лундстрам был САМЫМ важным защитником в этом году, предлагая огромную ценность при затратах: 26,1. Впечатляющий!

Самый важный вывод из всего этого анализа заключается в том, что вратари и защитники более ценны, чем полузащитники и нападающие. Но если вы просмотрите FPL Twitter, вы увидите много менеджеров FPL, которые не совсем понимают эту идею. Это, друг мой, называется «возможностью».

Конечно, ценность не все. Это задача оптимизации команды. У вас есть 100 денежных единиц, которые вы можете потратить, и команда ценных возвращающихся может не набрать достаточно очков, чтобы бросить вызов высокому результату в вашей мини-лиге или в целом. Команда тех, кто вернет наивысшую ценность, оставит вам немного денег в банке. И игра состоит в том, чтобы использовать ваши деньги для ПУНКТОВ, а не СТОИМОСТИ.

Давайте посмотрим на лучших полузащитников, например:

Кантуэлл предлагает наивысшую ценность из всех полузащитников, но у него по-прежнему всего 100 очков. Между тем, Де Брюйне имеет ценность всего 16,8, но в сумме 178 очков ...

Смысл? Вам нужны как ценность, так и высокая доходность. Вы ищете баланс; сбалансированная оптимизация стоимости и баллов.

Шаг 5. Экспорт в CSV

Прежде чем мы уйдем, я хотел показать вам, как экспортировать в CSV, с которым вы можете работать в Google Таблицах или Excel.

Это просто:

slim_elements_df.to_csv('~/Desktop/fpl_data.csv')

Запустите эту камеру и Бум! Выполнено. Хорошая работа :)

Теперь получайте удовольствие, исследуя данные в Google Таблицах или Excel, если вам это нравится.

Конец

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

Давайте дадим себе пять за наши новые идеи и навыки и приготовимся к захватывающему завершению сезона 19/20 FPL!

Хотите большего? Что-нибудь, что вас интересует, не было рассмотрено здесь в этом руководстве? Поделитесь своим запросом в комментарии здесь или напишите в Twitter @ deallen7

Ваше здоровье.