Одна из задач аналитика данных — обработать и представить данные в наглядном виде. Это нужно для того, чтобы, глядя на картинку, можно было легко понять, что происходит и что нужно делать дальше.
Данные можно представить по-разному: диаграммой, графиком, точками, распределением, тепловой картой и ещё десятком вариантов. Хороший аналитик знает, какой способ подходит для каких случаев, — теперь узнаете и вы. Мы подобрали 5 красивых визуализаций на Python, которые помогут разобраться с данными в самых разных ситуациях.
Что понадобится
Для визуализации нужен Python с разными библиотеками и сами данные. С Python проще всего: идём на официальный сайт, качаем последнюю версию и устанавливаем на компьютер. Если нужны подробности — держите наше руководство по установке и настройке Python:
Второй компонент — данные. Для экспериментов мы возьмём свободно доступные в интернете наборы данных (датасеты), причём будем загружать их напрямую из интернета. Но на всякий случай сохраните себе копии, вдруг те файлы удалят или отключат серверы.
raw.githubusercontent.com_selva86_datasets_master_midwest_filter.csv — данные о населении в провинциальной части США (Midwest)
raw.githubusercontent.com_selva86_datasets_master_mpg_ggplot2.csv — данные об автомобилях, их базовых характеристиках и производителях
raw.githubusercontent.com_selva86_datasets_master_mtcars.csv — тоже данные об автомобилях, но более детальные с технической точки зрения
raw.githubusercontent.com_selva86_datasets_master_gdppercap.csv — сведения о ВВП по частям света
Также мы будем использовать встроенный датасет про ирисы — данные о сортах цветов, длине листьев и прочие подробности. Он уже идёт в комплекте с библиотекой seaborn и сделан специально для обучения и тренировок по работе с данными.
Предварительная настройка
Перед тем как заниматься графикой, сделаем общие настройки визуализации:
- подключим библиотеки для работы с данными и с графикой;
- укажем нужные параметры отображения;
- выберем стиль оформления графиков.
Это будут общие настройки для каждого типа визуализации. Это значит, что в скрипт сначала нужно закинуть этот код, а следом за ним — код для конкретного графика. Если компьютер будет ругаться, что у него нет какой-то библиотеки, например pandas, установите их командой
pip install имя_библиотеки
# подключаем библиотеки для работы с данными и графикой
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
# переменные для настройки графиков
large = 22; med = 16; small = 12
# параметры графиков
params = {'axes.titlesize': large,
'legend.fontsize': med,
'figure.figsize': (16, 10),
'axes.labelsize': med,
'axes.titlesize': med,
'xtick.labelsize': med,
'ytick.labelsize': med,
'figure.titlesize': large}
# обновляем параметры
plt.rcParams.update(params)
# выбираем стили оформления
plt.style.use('seaborn-whitegrid')
sns.set_style("white")
Точечный график
Это один из основных графиков в работе аналитика данных. Он показывает взаимосвязь между двумя переменными, например между ценой и количеством продаж одного и того же товара в разных магазинах города. Каждая точка на графике — это пересечениие двух значений переменных. Глядя на расположение и группировку этих точек, можно сделать выводы, в каких случаях одно связано с другим.
Часто на графике рисуют несколько точечных графиков, где каждый набор данных показан своим цветом. Иногда это помогает найти связь между разными данными и сделать правильные выводы.
В нашем случае мы будем смотреть на данные демографического исследования провинциальной Америки (Midwest): как там связано население и площадь определённого графства (по-английски — county, по-нашему — что-то вроде городского округа).
# берём исходные данные из файла
midwest = pd.read_csv("https://raw.githubusercontent.com/selva86/datasets/master/midwest_filter.csv")
# берём столько категорий и цветов, сколько элементов в разделе ['category']
categories = np.unique(midwest['category'])
colors = [plt.cm.tab10(i/float(len(categories)-1)) for i in range(len(categories))]
# рисуем график для каждой категории
plt.figure(figsize=(16, 10), dpi= 80, facecolor='w', edgecolor='k')
# перебираем все значения и ставим точки на графике
for i, category in enumerate(categories):
# указываем, что это точечный график
plt.scatter('area', 'poptotal',
data=midwest.loc[midwest.category==category, :],
s=20, c=colors[i], label=str(category))
# добавляем разметку и подписи
plt.gca().set(xlim=(0.0, 0.1), ylim=(0, 90000),
xlabel='Площадь', ylabel='Численность')
# разметка графиков
plt.xticks(fontsize=12); plt.yticks(fontsize=12)
# добавляем название к графику
plt.title("Scatterplot of Midwest Area vs Population", fontsize=22)
# рисуем точечный график
plt.legend(fontsize=12)
plt.show()
Парный график
Если нужно полноценно и со всех сторон изучить связь одних данных с другими, используют парный график.
Мы возьмём встроенный в библиотеку датасет про лепестки ириса. График покажет связь между тремя сортами ириса (setosa, versicolor и virginica) и длиной их лепестков (sepal и petal). Если по-человечески это потом расшифровать, вы поймёте, какие лепестки у каких сортов ириса бывают и как одни отличить от других.
Парный график будет визуализизирован двумя способами: точками данных и графиком частотности каких-то данных. Точки — понятно: вот есть конкретные образцы ириса, вот такие у него лепестки. А частотность интересна: благодаря ей можно увидеть, насколько часто какие-то значения встречаются в каком-то диапазоне. Например, в самой первой ячейке будет видно, что у сорта setosa длина лепестка Sepal чаще всего маленькая, а у versicolor и virginica бывают разные, но в целом они подлиннее. Это, получается, выводы по одному конкретному измерению данных.
# берём исходные данные из файла
df = sns.load_dataset('iris')
# формируем и рисуем график
plt.figure(figsize=(10,8), dpi= 80)
sns.pairplot(df, kind="scatter", hue="species", plot_kws=dict(s=80, edgecolor="white", linewidth=2.5))
plt.show()
Расходящиеся столбцы
Если нужно показать положение каждого раздела относительно чего-то общего, используют расходящиеся столбцы. По ним сразу понятно, как данные располагаются друг относительно друга и нет ли там каких-то аномалий или нестыковок.
Сейчас посмотрим, каково расхождение пробега в милях на одном галлоне топлива (это примерно 4 литра). Мили и галлоны у нас из-за того, что датасет — американский, а там расход топлива измеряют не в литрах на сотню километров, а в том, сколько миль проедет машина на одном галлоне топлива. Мы построим график, который покажет машины со средним запасом хода и машины, которые могут проехать больше или меньше миль на одном галлоне топлива. Чем выше показатель — на столько миль больше эта машина проедет относительно среднего значения.
Например, мы сразу увидим, что у Ferrari Dino — средний из всех показатель такого запаса хода, а Toyota Corolla проедет на 2 мили больше на том же галлоне топлива.
# берём исходные данные из файла
df = pd.read_csv("https://github.com/selva86/datasets/raw/master/mtcars.csv")
# считаем пробег
x = df.loc[:, ['mpg']]
df['mpg_z'] = (x - x.mean())/x.std()
# выбираем цвет
df['colors'] = ['red' if x < 0 else 'green' for x in df['mpg_z']]
# сортируем значения
df.sort_values('mpg_z', inplace=True)
df.reset_index(inplace=True)
# готовим графие
plt.figure(figsize=(14,10), dpi= 80)
plt.hlines(y=df.index, xmin=0, xmax=df.mpg_z, color=df.colors, alpha=0.4, linewidth=5)
# подписи осей
plt.gca().set(ylabel='$Модель$', xlabel='$Пробег$')
plt.yticks(df.index, df.cars, fontsize=12)
# название графика
plt.title('Распределение моделей относительно среднего пробега', fontdict={'size':20})
plt.grid(linestyle='--', alpha=0.5)
# показываем график
plt.show()
Упорядоченная гистограмма
Эта визуализация нужна, когда нужно быстро окинуть взглядом какой-то набор данных и получить первое представление — что там происходит и чему равны значения на разных позициях. Например, так мы можем сразу найти автопроизводителей с самым большим запасом хода относительно топлива:
# берём исходные данные из файла
df_raw = pd.read_csv("https://github.com/selva86/datasets/raw/master/mpg_ggplot2.csv")
# отбираем расход топлива по производителям
df = df_raw[['cty', 'manufacturer']].groupby('manufacturer').apply(lambda x: x.mean())
df.sort_values('cty', inplace=True)
df.reset_index(inplace=True)
# подключаем модуль из библиотеки
import matplotlib.patches as patches
# настраиваем общий вид графика
fig, ax = plt.subplots(figsize=(16,10), facecolor='white', dpi= 80)
ax.vlines(x=df.index, ymin=0, ymax=df.cty, color='firebrick', alpha=0.7, linewidth=20)
# добавляем подписи
for i, cty in enumerate(df.cty):
ax.text(i, cty+0.5, round(cty, 1), horizontalalignment='center')
# названия осей и значения
ax.set_title('Средний расход топлива за городом', fontdict={'size':22})
ax.set(ylabel='Миль на галлон', ylim=(0, 30))
plt.xticks(df.index, df.manufacturer.str.upper(), rotation=60, horizontalalignment='right', fontsize=12)
# формируем зелёную и красную зоны
p1 = patches.Rectangle((.57, -0.005), width=.33, height=.13, alpha=.1, facecolor='green', transform=fig.transFigure)
p2 = patches.Rectangle((.124, -0.005), width=.446, height=.13, alpha=.1, facecolor='red', transform=fig.transFigure)
# добавляем всё на график и показываем его
fig.add_artist(p1)
fig.add_artist(p2)
plt.show()
График «До — после»
Есть график, который показывает состояние «до» и «после» и динамику этих изменений. С помощью такого графика легко увидеть общие тренды и некоторые аномалии. Например, сразу видно, что за 5 лет ВВП на душу населения выросло во всех регионах, кроме Азии, — там он показал спад. Почему и как это произошло — следующая задача аналитиков, но зато сразу понятно, на что обратить внимание.
# подключаем нужный модуль из графической библиотеки
import matplotlib.lines as mlines
# берём исходные данные из файла
df = pd.read_csv("https://raw.githubusercontent.com/selva86/datasets/master/gdppercap.csv")
# добавляем надписи на колонки До и После
left_label = [str(c) + ', '+ str(round(y)) for c, y in zip(df.continent, df['1952'])]
right_label = [str(c) + ', '+ str(round(y)) for c, y in zip(df.continent, df['1957'])]
klass = ['red' if (y1-y2) < 0 else 'green' for y1, y2 in zip(df['1952'], df['1957'])]
# рисуем линии
def newline(p1, p2, color='black'):
ax = plt.gca()
# в зависимости от роста или падения рисуем зелёную или красную линии
l = mlines.Line2D([p1[0],p2[0]], [p1[1],p2[1]], color='red' if p1[1]-p2[1] > 0 else 'green', marker='o', markersize=6)
ax.add_line(l)
return l
# готовим график
fig, ax = plt.subplots(1,1,figsize=(14,14), dpi= 80)
# рисуем вертикальные линии
ax.vlines(x=1, ymin=500, ymax=13000, color='black', alpha=0.7, linewidth=1, linestyles='dotted')
ax.vlines(x=3, ymin=500, ymax=13000, color='black', alpha=0.7, linewidth=1, linestyles='dotted')
# ставим точки начала и конца в нужных местах на линиях
ax.scatter(y=df['1952'], x=np.repeat(1, df.shape[0]), s=10, color='black', alpha=0.7)
ax.scatter(y=df['1957'], x=np.repeat(3, df.shape[0]), s=10, color='black', alpha=0.7)
# добавляем надписи к каждой точке слева и справа
for p1, p2, c in zip(df['1952'], df['1957'], df['continent']):
newline([1,p1], [3,p2])
ax.text(1-0.05, p1, c + ', ' + str(round(p1)), horizontalalignment='right', verticalalignment='center', fontdict={'size':14})
ax.text(3+0.05, p2, c + ', ' + str(round(p2)), horizontalalignment='left', verticalalignment='center', fontdict={'size':14})
# добавляем надписи ДО и ПОСЛЕ
ax.text(1-0.05, 13000, 'ДО', horizontalalignment='right', verticalalignment='center', fontdict={'size':18, 'weight':700})
ax.text(3+0.05, 13000, 'ПОСЛЕ', horizontalalignment='left', verticalalignment='center', fontdict={'size':18, 'weight':700})
# оформляем график
ax.set_title("Изменение ВВП на душу населения в 1952 и 1957 годах", fontdict={'size':22})
ax.set(xlim=(0,4), ylim=(0,14000), ylabel='ВВП на душу населения')
ax.set_xticks([1,3])
ax.set_xticklabels(["1952", "1957"])
plt.yticks(np.arange(500, 13000, 2000), fontsize=12)
# убираем рамку вокруг графика
plt.gca().spines["top"].set_alpha(.0)
plt.gca().spines["bottom"].set_alpha(.0)
plt.gca().spines["right"].set_alpha(.0)
plt.gca().spines["left"].set_alpha(.0)
# показываем, что получилось
plt.show()
Нравится визуализация — где научиться
В Практикуме есть бесплатный курс «Основы анализа данных и Python» — там научат и строить графики, и понимать, что они означают, и как с этим работать дальше. Если понравится — присмотритесь к аналитике получше.
Что дальше
В следующий раз мы попробуем использовать эти графики в своих проектах и посмотрим, какие ещё способы визуализации используют дата-аналитики в работе.