Мне очень нравится играть в игры

Тема чемпионов League of Legends была выбрана благодаря интересу к киберспортивной аналитике и профессиональной сцене игры. Мне было интересно взглянуть на них не только с игровой, но и с аналитической стороны — выявить скрытые закономерности: эффективность чемпионов на турнирах, влияние стороны карты на результат, связь пикрейта с винрейтом. Этот проект позволил объединить любовь к киберспорту с навыками анализа данных.

В рамках проекта был проведен анализ данных чемпионов League of Legends с турнира Worlds Championship. Интерес к киберспортивной аналитике и профессиональной игровой сцене определил выбор темы. В процессе исследования удалось выявить ключевые закономерности: распределение побед между сторонами карты, корреляцию пикрейта и винрейта, а также наиболее эффективных чемпионов турнира. Проект стал удачным примером объединения увлечения киберспортом с профессиональными навыками анализа данных.
Для визуализации данных я планирую использовать следующие типы графиков: • Тепловая карта • Столбчатая диаграмма • Круговая диаграмма • Точечный график (scatter plots)
Визуальное оформление
Графики оформлены в оттенках игры, соответствующем тематике цветов.
Загрузка данных
Для работы я импортировала библиотеки: pandas для работы с данными, matplotlib.pyplot для построения графиков, и загрузила основной файл из датасета. Также, для тепловой карты, использовалась библиотека matplotlib.colors.
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns
Загрузка данных из папки Downloads
df = pd.read_csv (r’D:\Downloads\wc_champions (3).csv')
print («✅ Данные загружены!») print (f"Размер: {df.shape}») print (df.head ())
Круговая диаграмма
Была построена круговая диаграмма, отображающая распределение побед среди топ-5 чемпионов турнира. Для построения круговой диаграммы необходимо было отфильтровать данные по столбцу win_total, после чего нужно было выбрать 5 чемпионов с наибольшим количеством побед и рассчитать процентное соотношение их побед относительно общего числа побед в топ-5.
На круговой диаграмме представлено распределение побед среди топ-5 чемпионов турнира Worlds Championship. Для визуализации данных была использована пользовательская цветовая палитра, вдохновленная стилистикой League of Legends (золотой, темно-бирюзовый, бронзовый, серебристый, серый), а также настроен стиль текста для улучшения читаемости и эстетического восприятия диаграммы.
import pandas as pd import matplotlib.pyplot as plt from io import StringIO
Ваши данные (первые 10 чемпионов для примера, можно добавить всех)
data_text = «„„champion, sum_total, win_total, lose_total, pick_rate, winrate_total, sum_blue_side, win_blue_side, lose_blue_side, winrate_blue_side, sum_red_side, win_red_side, lose_red_side, winrate_red_side Graves, 69,35,34,50.72%, 60.53%, 34,17,17,50.00%, 35,18,17,51.43% Senna, 46,21,25,45.65%, 40.35%, 21,12,9,57.14%, 25,9,16,36.00% Jhin, 42,28,14,66.67%, 36.84%, 20,10,10,50.00%, 22,18,4,81.82% Leona, 42,26,16,61.90%, 36.84%, 19,14,5,73.68%, 23,12,11,52.17% Ashe, 42,17,25,40.48%, 36.84%, 15,5,10,33.33%, 27,12,15,44.44% Lillia, 41,17,24,41.46%, 35.96%, 22,9,13,40.91%, 19,8,11,42.11% Ornn, 40,24,16,60.00%, 35.09%, 21,13,8,61.90%, 19,11,8,57.89% Orianna, 39,25,14,64.10%, 34.21%, 16,12,4,75.00%, 23,13,10,56.52% Syndra, 37,19,18,51.35%, 32.46%, 23,13,10,56.52%, 14,6,8,42.86% Ezreal, 34,20,14,58.82%, 29.82%, 19,12,7,63.16%, 15,8,7,53.33%“»»
Загрузка данных
df = pd.read_csv (StringIO (data_text))
Просмотр данных
print («✅ Данные загружены!») print (f"\n📊 Размер данных: {df.shape[0]} строк, {df.shape[1]} столбцов») print (f"\n📋 Названия столбцов:») print (df.columns.tolist ())
print («\n🔍 Первые 5 строк:») print (df.head ())
Создаем круговую диаграмму для топ-5 чемпионов по победам
top_5_wins = df.nlargest (5, 'win_total')[['champion', 'win_total']] print («\n🏆 Топ-5 чемпионов по победам:») print (top_5_wins)
Цвета League of Legends (5 основных цветов)
colors = ['
C89B3C', '
0A323C', '785A28', '
A9B4C2', '#5E5E5E']Настройка стиля
plt.rcParams.update ({ 'font.size': 14, 'font.weight': 'bold', 'text.color': 'black' })
Построение круговой диаграммы
plt.figure (figsize=(10, 8)) wedges, texts, autotexts = plt.pie ( top_5_wins['win_total'], labels=top_5_wins['champion'], autopct='%1.1f%%', colors=colors, startangle=90, wedgeprops={'edgecolor': 'black', 'linewidth': 2}, textprops={'fontsize': 12, 'fontweight': 'bold'}, pctdistance=0.85 )
Настройка текста процентов
for autotext in autotexts: autotext.set_color ('white') autotext.set_fontweight ('bold') autotext.set_fontsize (12)
plt.title ('Топ-5 чемпионов по количеству побед\nWorlds Championship', fontsize=16, fontweight='bold', pad=20) plt.axis ('equal') plt.tight_layout () plt.show ()
Статистика
print (f"\n📊 Статистика:») print (f"Всего чемпионов в топ-5: {len (top_5_wins)}») print (f"Всего побед у топ-5: {top_5_wins['win_total'].sum ()}») for _, row in top_5_wins.iterrows (): print (f» {row['champion']}: {row['win_total']} побед»)
Точечный график
Благодаря этому точечному графику мы увидели, как связаны пикрейт чемпиона и его винрейт на турнире. А также различия в этих показателях между чемпионами с разным количеством сыгранных матчей.
После фильтрации чемпионов с высоким пикрейтом (более 40%) от менее популярных видов, я приступила к построению графика. На нём каждая точка представляет отдельного чемпиона, а цвет точки соответствует количеству сыгранных им матчей (размер точки также отражает этот показатель). Это позволило наглядно увидеть, какие чемпионы демонстрируют высокую эффективность при высокой популярности, а какие — показывают хороший винрейт, оставаясь в тени более популярных собратьев.
from io import StringIO import pandas as pd import matplotlib.pyplot as plt
Ваши данные
data = «„„champion, sum_total, win_total, lose_total, pick_rate, winrate_total, sum_blue_side, win_blue_side, lose_blue_side, winrate_blue_side, sum_red_side, win_red_side, lose_red_side, winrate_red_side Graves, 69,35,34,50.72%, 60.53%, 34,17,17,50.00%, 35,18,17,51.43% Senna, 46,21,25,45.65%, 40.35%, 21,12,9,57.14%, 25,9,16,36.00% Jhin, 42,28,14,66.67%, 36.84%, 20,10,10,50.00%, 22,18,4,81.82% Leona, 42,26,16,61.90%, 36.84%, 19,14,5,73.68%, 23,12,11,52.17% Ashe, 42,17,25,40.48%, 36.84%, 15,5,10,33.33%, 27,12,15,44.44% Lillia, 41,17,24,41.46%, 35.96%, 22,9,13,40.91%, 19,8,11,42.11% Ornn, 40,24,16,60.00%, 35.09%, 21,13,8,61.90%, 19,11,8,57.89% Orianna, 39,25,14,64.10%, 34.21%, 16,12,4,75.00%, 23,13,10,56.52% Syndra, 37,19,18,51.35%, 32.46%, 23,13,10,56.52%, 14,6,8,42.86% Ezreal, 34,20,14,58.82%, 29.82%, 19,12,7,63.16%, 15,8,7,53.33%“»»
Загрузка данных
df = pd.read_csv (StringIO (data))
Очищаем процентные значения
df['pick_rate'] = df['pick_rate'].str.rstrip ('%').astype (float) df['winrate_total'] = df['winrate_total'].str.rstrip ('%').astype (float) df['winrate_blue_side'] = df['winrate_blue_side'].str.rstrip ('%').astype (float) df['winrate_red_side'] = df['winrate_red_side'].str.rstrip ('%').astype (float)
print («✅ Данные загружены!») print (f"📊 Всего чемпионов: {len (df)}»)
Фильтруем данные — оставляем чемпионов с высоким пикрейтом (pick_rate > 40%)
df_popular = df[df['pick_rate'] > 40]
print (f"\n🔍 Чемпионов с пикрейтом > 40%: {len (df_popular)}»)
Проверяем, есть ли данные
if not df_popular.empty:
# Цветовая палитра League of Legends
colors = ['<h3>C89B3C', '</h3>0A323C', '<h3>785A28', '</h3>A9B4C2', '<h3>5E5E5E', '</h3>F0E6D2']
# Создаем словарь цветов для разных ролей (если есть данные о ролях)
# В данном случае используем категории по количеству игр
df_popular['category'] = pd.cut (df_popular['sum_total'],
bins=[0, 30, 50, 100],
labels=['Мало игр (0-30)', 'Средне игр (30-50)', 'Много игр (50\+)'])
unique_categories = df_popular['category'].unique ()
color_map = {category: colors[i % len (colors)] for i, category in enumerate (unique_categories)}
Строим точечный график зависимости винрейта от пикрейта
plt.figure (figsize=(12, 8))
for category in unique_categories:
subset = df_popular[df_popular['category'] == category]
plt.scatter (subset['pick_rate'],
subset['winrate_total'],
c=color_map[category],
label=category,
s=subset['sum_total'] * 2, # Размер точки зависит от количества игр
alpha=0.7,
edgecolor='black',
linewidth=1.5)
# Добавляем подписи для самых заметных чемпионов
for _, row in subset.iterrows ():
if row['sum_total'] > 40: # Подписываем только популярных чемпионов
plt.annotate (row['champion'],
(row['pick_rate'], row['winrate_total']),
xytext=(5, 5),
textcoords='offset points',
fontsize=9,
fontweight='bold')
# Улучшаем внешний вид
plt.grid (True, linestyle='--', alpha=0.7)
plt.xlabel ('Пикрейт (%)', fontsize=12, fontweight='bold')
plt.ylabel ('Винрейт (%)', fontsize=12, fontweight='bold')
plt.title ('Зависимость винрейта от пикрейта среди чемпионов\nWorlds Championship',
fontsize=14, fontweight='bold', pad=20)
plt.legend (title='Количество игр', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout ()
# Отображаем график
plt.show ()
# Выводим статистику
print (f"\n📊 Статистика:»)
print (f"Всего чемпионов с пикрейтом > 40%: {len (df_popular)}»)
print (f"Средний пикрейт: {df_popular['pick_rate'].mean ():.1f}%»)
print (f"Средний винрейт: {df_popular['winrate_total'].mean ():.1f}%»)
print (f"\n📈 Корреляция между пикрейтом и винрейтом: {df_popular['pick_rate'].corr (df_popular['winrate_total']):.3f}»)
print (f"\n🏆 Распределение по количеству игр:»)
print (df_popular['category'].value_counts ())
else: print («⚠️ Нет чемпионов с пикрейтом > 40%»)
Для понимания графика, я сделала подписи к осям Х и Y.
Добавляем подписи для самых заметных чемпионов
for _, row in subset.iterrows ():
if row['sum_total'] > 40: # Подписываем только популярных чемпионов
plt.annotate (row['champion'],
(row['pick_rate'], row['winrate_total']),
xytext=(5, 5),
textcoords='offset points',
fontsize=9,
fontweight='bold')
Тепловая карта
Для построения тепловой карты я определила топ-5 чемпионов, одержавших наибольшее количество побед на турнире Worlds Championship. Затем сгруппировала данные по этим чемпионам и признаку эффективности на разных сторонах карты (синяя и красная), чтобы выявить, на какой стороне лидеры турнира демонстрируют лучшие результаты. На основе этих данных построила тепловую карту, где интенсивность цвета отображает винрейт чемпиона на соответствующей стороне.
from io import StringIO import pandas as pd import numpy as np import matplotlib.pyplot as plt
Ваши данные (полные)
data = «„„champion, sum_total, win_total, lose_total, pick_rate, winrate_total, sum_blue_side, win_blue_side, lose_blue_side, winrate_blue_side, sum_red_side, win_red_side, lose_red_side, winrate_red_side Graves, 69,35,34,50.72%, 60.53%, 34,17,17,50.00%, 35,18,17,51.43% Senna, 46,21,25,45.65%, 40.35%, 21,12,9,57.14%, 25,9,16,36.00% Jhin, 42,28,14,66.67%, 36.84%, 20,10,10,50.00%, 22,18,4,81.82% Leona, 42,26,16,61.90%, 36.84%, 19,14,5,73.68%, 23,12,11,52.17% Ashe, 42,17,25,40.48%, 36.84%, 15,5,10,33.33%, 27,12,15,44.44% Lillia, 41,17,24,41.46%, 35.96%, 22,9,13,40.91%, 19,8,11,42.11% Ornn, 40,24,16,60.00%, 35.09%, 21,13,8,61.90%, 19,11,8,57.89% Orianna, 39,25,14,64.10%, 34.21%, 16,12,4,75.00%, 23,13,10,56.52% Syndra, 37,19,18,51.35%, 32.46%, 23,13,10,56.52%, 14,6,8,42.86% Ezreal, 34,20,14,58.82%, 29.82%, 19,12,7,63.16%, 15,8,7,53.33%“»»
Загрузка данных
df = pd.read_csv (StringIO (data))
Очищаем процентные значения
df['winrate_total'] = df['winrate_total'].str.rstrip ('%').astype (float) df['winrate_blue_side'] = df['winrate_blue_side'].str.rstrip ('%').astype (float) df['winrate_red_side'] = df['winrate_red_side'].str.rstrip ('%').astype (float) df['pick_rate'] = df['pick_rate'].str.rstrip ('%').astype (float)
print («✅ Данные загружены!») print (f"📊 Всего чемпионов: {len (df)}»)
1. Выбираем топ-5 чемпионов по количеству побед
top_5_champions = df.nlargest (5, 'win_total')['champion'].tolist ()
2. Фильтруем DataFrame по этим чемпионам
df_top = df[df['champion'].isin (top_5_champions)].copy ()
3. Создаем столбцы с винрейтом на синей и красной стороне
df_top['blue_text'] = 'Винрейт на синей стороне' df_top['red_text'] = 'Винрейт на красной стороне'
4. Строим сводную таблицу: чемпион → сторона → винрейт
pivot_df = df_top.pivot_table ( index='champion', values=['winrate_blue_side', 'winrate_red_side'], aggfunc='mean' )
Переименовываем колонки для читаемости
pivot_df.columns = ['Винрейт на синей стороне (%)', 'Винрейт на красной стороне (%)']
5. Сортируем чемпионов по общему винрейту (для наглядности)
pivot_df['avg_winrate'] = (pivot_df['Винрейт на синей стороне (%)'] + pivot_df['Винрейт на красной стороне (%)']) / 2 pivot_df = pivot_df.sort_values ('avg_winrate', ascending=False) pivot_df = pivot_df.drop ('avg_winrate', axis=1)
6. Создаем тепловую карту с помощью matplotlib
fig, ax = plt.subplots (figsize=(10, 6))
Цветовая карта League of Legends (от зеленого/золотого к красному/темному)
colors = ['
C89B3C', '
785A28', '0A323C', '
5E5E5E', '#F0E6D2'] cmap = plt.cm.colors.ListedColormap (colors[: len (pivot_df.columns)])Рисуем тепловую карту
im = ax.imshow (pivot_df.values, cmap='RdYlGn', aspect='auto', vmin=30, vmax=80)
Настройка осей
ax.set_xticks (np.arange (len (pivot_df.columns))) ax.set_yticks (np.arange (len (pivot_df.index))) ax.set_xticklabels (pivot_df.columns, rotation=15, ha='right', fontsize=11, fontweight='bold') ax.set_yticklabels (pivot_df.index, fontsize=11, fontweight='bold')
Добавляем значения в ячейки
for i in range (len (pivot_df.index)): for j in range (len (pivot_df.columns)): value = pivot_df.values[i, j] text_color = 'white' if value < 50 or value > 70 else 'black' text = ax.text (j, i, f'{value:.1f}%', ha="center», va="center», color=text_color, fontweight='bold', fontsize=12)
Настройка внешнего вида
ax.set_xlabel ('Сторона карты', fontsize=12, fontweight='bold') ax.set_ylabel ('Чемпион', fontsize=12, fontweight='bold') ax.set_title ('Сравнение эффективности топ-5 чемпионов\nна синей и красной стороне\nWorlds Championship', fontsize=14, fontweight='bold', pad=20)
Добавляем цветовую шкалу
cbar = plt.colorbar (im, ax=ax, shrink=0.8) cbar.set_label ('Винрейт (%)', fontsize=11, fontweight='bold')
Добавляем рамки между ячейками
for i in range (len (pivot_df.index) + 1): ax.axhline (i — 0.5, color='white', linewidth=2) for j in range (len (pivot_df.columns) + 1): ax.axvline (j — 0.5, color='white', linewidth=2)
plt.tight_layout () plt.show ()
Выводим статистику
print («\n📊 СТАТИСТИКА:») print (f"Всего чемпионов в топ-5: {len (df_top)}») print (f"\n🏆 Топ-5 чемпионов по количеству побед:») for i, champion in enumerate (top_5_champions, 1): champ_data = df[df['champion'] == champion].iloc[0] print (f"{i}. {champion}: {champ_data['win_total']} побед (всего игр: {champ_data['sum_total']})»)
print (f"\n📈 Распределение винрейта по сторонам:») print (pivot_df.round (1))
Столбчатая диаграмма
Для визуализации распределения популярности среди чемпионов я построила горизонтальный барчарт, отображающий топ-5 чемпионов по количеству побед на турнире Worlds Championship. Для построения диаграммы использовалась пользовательская цветовая палитра, вдохновленная стилистикой League of Legends (золотой, темно-бирюзовый, бронзовый, серебристый, серый), а также настроен стиль текста для улучшения читаемости и эстетического восприятия. На диаграмме каждый столбец представляет отдельного чемпиона, а его длина соответствует количеству одержанных побед.
from io import StringIO import pandas as pd import matplotlib.pyplot as plt
Загрузка данных
df = pd.read_csv (StringIO (data))
Очищаем процентные значения
df['pick_rate'] = df['pick_rate'].str.rstrip ('%').astype (float)
print («✅ Данные загружены!»)
Цветовая палитра League of Legends
my_colors = ['
C89B3C', '
0A323C', '785A28', '
A9B4C2', '#5E5E5E']Подсчёт пикрейта по чемпионам
champion_pick = df.set_index ('champion')['pick_rate']
Определяем топ-5 чемпионов по пикрейту
top_5_pick = champion_pick.nlargest (5)
Стиль оформления
plt.style.use ('default') plt.rcParams.update ({ 'text.color': 'black', 'axes.labelcolor': 'black', 'xtick.color': 'black', 'ytick.color': 'black', 'font.size': 12, 'axes.titleweight': 'bold', 'axes.labelweight': 'bold' })
Создание горизонтального барчарта
plt.figure (figsize=(10, 6)) bars = plt.barh ( y=top_5_pick.index, width=top_5_pick.values, color=my_colors[: len (top_5_pick)], edgecolor='black', linewidth=1.5 )
Добавление значений на столбцы
for i, (champion, pick_rate) in enumerate (top_5_pick.items ()): winrate = df[df['champion'] == champion]['winrate_total'].values[0] plt.text (pick_rate + 0.5, i, f'{pick_rate:.1f}%\n (винрейт {winrate:.1f}%)', color='black', va='center', fontsize=10, fontweight='bold')
Заголовок и подписи
plt.title ('Топ-5 чемпионов по пикрейту (популярности)\nWorlds Championship', fontsize=16, pad=20, fontweight='bold') plt.xlabel ('Пикрейт (%)', fontsize=14, fontweight='bold') plt.ylabel ('Чемпион', fontsize=14, fontweight='bold')
Добавляем сетку
plt.grid (axis='x', linestyle='--', alpha=0.7, color='gray')
Убираем лишние рамки
plt.gca ().spines['top'].set_visible (False) plt.gca ().spines['right'].set_visible (False)
plt.tight_layout () plt.show ()
Выводим статистику
print («\n📊 СТАТИСТИКА:») print (f"Всего чемпионов в базе: {len (df)}») print (f"Средний пикрейт топ-5: {top_5_pick.mean ():.1f}%») print (f"\n🏆 Топ-5 чемпионов по пикрейту:») for i, (champion, pick_rate) in enumerate (top_5_pick.items (), 1): total_games = df[df['champion'] == champion]['sum_total'].values[0] winrate = df[df['champion'] == champion]['winrate_total'].values[0] print (f"{i}. {champion}: {pick_rate:.1f}% ({total_games} игр, винрейт {winrate:.1f}%)»)
Заключение
В ходе работы был проведён анализ датафрейма, содержащего информацию о чемпионах League of Legends на турнире Worlds Championship: количество сыгранных матчей, одержанных побед и поражений, пикрейт (популярность), общий винрейт, а также эффективность на синей и красной сторонах карты. На основе полученных результатов были построены графики и диаграммы (круговая диаграмма, точечный график, тепловая карта, горизонтальный барчарт), позволяющие наглядно представить выявленные закономерности и сделать выводы о влиянии стороны карты на успешность чемпионов, корреляции между популярностью и эффективностью, а также определить лидеров турнира по ключевым показателям.
Описание применения генеративной модели
В ходе работы над проектом использовались следующие нейросети:
Работа с генеративной моделью велась в интерактивном режиме через веб-интерфейс. Пользователем формулировались текстовые запросы (промпты), на основе которых модель генерировала код Python, объяснения и текстовые описания. При необходимости выполнитель уточнял запросы, корректировал сгенерированный код и интегрировал его в общую структуру проекта.
Генеративная модель использовалась для решения следующих задач:
Создание скриптов для загрузки данных из CSV-файла в pandas, преобразования процентных значений (например, «50.72%») в числовые форматы, группировки данных по чемпионам и построения визуализаций
Генерация структурированных ответов на вопросы о статистических методах, стилизации графиков в стилистике League of Legends и интерпретации полученных результатов
Создание кода для чтения CSV-файла с чемпионами в pandas: «Напиши код на Python для загрузки CSV в pandas, где данные содержат информацию о чемпионах League of Legends: название, количество побед, пикрейт, винрейт на синей и красной сторонах»
Создание круговых, точечных диаграмм, тепловых карт и барчартов: «Создай круговую диаграмму для топ-5 чемпионов по победам с цветовой палитрой League of Legends:
C89B3C,
0A323C,785A28,
A9B4C2, #5E5E5E» / «Построй точечный график зависимости винрейта от пикрейта чемпионов, используемых на турнире Worlds Championship»Исправление проблем с установкой библиотек, предупреждений pandas и стилизацией графиков: «Как исправить SettingWithCopyWarning в pandas при создании нового столбца в отфильтрованном DataFrame?» / «Как установить seaborn в Colab?» / «Как настроить цветовую палитру в matplotlib под стиль League of Legends?»
Применение генеративной модели позволило:
Сократить время разработки — автоматизация рутинных задач по написанию кода для загрузки, очистки и визуализации данных
Повысить качество кода — использование современных практик и рекомендаций pandas, matplotlib для построения качественных графиков
Упростить процесс обучения — получение пояснений к сложным конструкциям, таким как работа с тепловыми картами или точечными диаграммами
Обеспечить единообразие стиля — генерация кода с соблюдением единого стиля оформления и цветовой гаммы, соответствующей тематике проекта



