Качественно новый уровень визуализации данных в Python

Обложка поста

Перевод статьи «The Next Level of Data Visualization in Python»

Рассказывает Уилл Кёрсен, data scientist в Cortex Intel


Нам сложно отказываться от дел, на которые мы уже потратили много времени. Поэтому мы остаёмся на нелюбимой работе, вкладываемся в проекты, которые точно не «взлетят». А ещё продолжаем пользоваться утомительной библиотекой matplotlib для построения графиков, когда есть более эффективные и привлекательные альтернативы.

За последние несколько месяцев я осознал, что единственная причина, по которой я пользуюсь matplotlib, заключается в том, что я потратил сотни часов на изучение её запутанного синтаксиса. Из-за неё я жил на StackOverflow, пытаясь найти ответ на тот или иной вопрос. К счастью, для создания графиков на Python настали светлые времена, и после изучения доступных вариантов я выбрал явного победителя (с точки зрения простоты использования, документации и функциональности) в лице библиотеки plotly. В этой статье мы с ней познакомимся и научимся делать более качественные графики за меньшее время — зачастую с помощью одной строки кода.

Весь код для этой статьи доступен на GitHub. Все графики интерактивны, а посмотреть их можно на NBViewer.

Пример графиков plotly (источник)

Обзор plotly

Пакет plotly для Python — это open-source библиотека, основанная на plotly.js, которая, в свою очередь, основана на d3.js. Мы будем использовать обёртку для plotly под названием cufflinks, написанную для работы с DataFrame’ами Pandas.

Вообще, Plotly — это графическая компания с несколькими продуктами и open-source инструментами. Библиотека на Python бесплатна для использования, и мы можем создавать графики без ограничений в офлайн-режиме плюс до 25 графиков в онлайн-режиме.

Весь код из этой статьи был написан в Jupyter Notebook с plotly + cufflinks, запущенными в офлайн-режиме. После установки plotly и cufflinks с помощью pip install cufflinks plotly добавьте следующие импорты в блокнот Jupyter:

# Стандартные импорты plotly
import plotly.plotly as py
import plotly.graph_obs as go
from plotly.offline import iplot
import cufflinks
cufflinks.go_offline()
# Устанавливаем глобальную тему 
cf.set_config_file(world_readable=True, theme='pearl', offline=True)

Гистограммы и бочки с усами

Графики по одной переменной — стандартный способ начать анализ, а гистограмма — надёжный выбор (хоть и не без изъянов) для отображения распределения. Давайте нарисуем интерактивную гистограмму количества лайков, используя статистику моих постов на Medium (df это обычный DataFrame):

df['claps'].iplot(kind='hist', xTitle='claps',
                  yTitle='count', title='Claps Distribution')

Интерактивная гистограмма, созданная с помощью plotly + cufflinks

Если вы работали с matplotlib, то вы заметили, что нам пришлось добавить всего одну букву (iplot() вместо plot()), чтобы получить гораздо более красивый и интерактивный график! Можно кликнуть на данные для получения подробностей, приблизить части графика и, как мы потом увидим, выбирать отдельные категории для просмотра.

А вот так можно построить наложенные друг на друга гистограммы:

df[['time_started', 'time_published']].iplot(
    kind='hist',
    histnorm='percent',
    barmode='overlay',
    xTitle='Time of Day',
    yTitle='(%) of Articles',
    title='Time Started and Time Published')

Немного поколдовав с pandas, получим столбчатую диаграмму:

# Создаём DataFrame с месячной частотой и строим график
df2 = df[['view','reads','published_date']].\
         set_index('published_date').\
         resample('M').mean()
df2.iplot(kind='bar', xTitle='Date', yTitle='Average',
    title='Monthly Average Views and Reads')

Как видите, мы можем совмещать возможности pandas и plotly + cufflinks. Для графика «ящик с усами», который показывает количество лайкнувших каждый пост, мы сначала используем pivot(), а затем строим график:

df.pivot(columns='publication', values='fans').iplot(
        kind='box',
        yTitle='fans',
        title='Fans Distribution by Publication')

Преимущества интерактивности заключаются в том, что мы можем исследовать данные и делать их выборки любым образом. Ящик с усами содержит много информации, большая часть которой пройдёт мимо нас, если мы не сможем видеть числа!

Диаграмма рассеяния

Это, наверное, наиболее часто используемая диаграмма при анализе данных. Она позволяет увидеть изменение переменной с течением времени или отношение между двумя (или более) переменными.

Временные ряды

В значительной части данных содержится информация о времени. К счастью, plotly + cufflinks были разработаны с расчётом на визуализацию временных рядов. Создадим DataFrame с моими статьями и посмотрим, как менялись тренды.

# Создаём DataFrame со статьями Towards Data Science
tds = df[df['publication'] == 'Towards Data Science'].\
         set_index('published_date')
# Строим продолжительность чтения как временной ряд
tds[['claps', 'fans', 'title']].iplot(
    y='claps', mode='lines+markers', secondary_y = 'fans',
    secondary_y_title='Fans', xTitle='Date', yTitle='Claps',
    text='title', title='Fans and Claps over Time')

Здесь мы в одну строку делаем сразу несколько разных вещей:

  • Автоматически получаем красиво отформатированную ось X;
  • Добавляем дополнительную ось Y, так как у переменных разные диапазоны;
  • Добавляем заголовки статей, которые высвечиваются при наведении курсора.

Для большей наглядности можно легко добавить текстовые аннотации:

tds_monthly_totals.iplot(
    mode='lines+markers+text',
    text=text,
    y='word_count',
    opacity=0.8,
    xTitle='Date',
    yTitle='Word Count',
    title='Total Word Count by Month')

Диаграмма рассеяния с аннотациями

А вот так можно создать точечную диаграмму с двумя переменными, окрашенными согласно третьей категориальной переменной:

df.iplot(
    x='read_time',
    y='read_ratio',
    # Указываем категорию
    categories='publication',
    xTitle='Read Time',
    yTitle='Reading Percent',
    title='Reading Percent vs Read Ratio by Publication')

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

tds.iplot(
    x='word_count',
    y='reads',
    size='read_ratio',
    text=text,
    mode='markers',
    # Log xaxis
    layout=dict(
        xaxis=dict(type='log', title='Word Count'),
        yaxis=dict(title='Reads'),
        title='Reads vs Log Word Count Sized by Read Ratio'))

Если захотеть (подробности в блокноте), то можно уместить даже 4 переменные (не советую) на одном графике!

Как и раньше, мы совмещаем возможности pandas и plotly + cufflinks для получения полезных графиков:

df.pivot_table(
    values='views', index='published_date',
    columns='publication').cumsum().iplot(
        mode='markers+lines',
        size=8,
        symbol=[1, 2, 3, 4, 5],
        layout=dict(
            xaxis=dict(title='Date'),
            yaxis=dict(type='log', title='Total Views'),
            title='Total Views over Time by Publication'))

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

Продвинутые графики

Теперь познакомимся с несколькими графиками, которые используются не так часто, но могут выглядеть довольно впечатляюще. Мы воспользуемся plotly.figure_factory(), чтобы даже эти невероятные графики создавать в одну строку.

Матрица рассеяния

Матрица рассеяния — отличный выбор, если нам нужно изучить отношения между многими переменными:

import plotly.figure_factory as ff
figure = ff.create_scatterplotmatrix(
    df[['claps', 'publication', 'views',      
        'read_ratio','word_count']],
    diag='histogram',
    index='publication')

Даже этот график полностью интерактивен, что позволяет нам исследовать данные.

Корреляционная тепловая карта

Чтобы отобразить взаимосвязи между числовыми переменными, сначала посчитаем коэффициенты корреляции, а затем создадим аннотированную тепловую карту:

corrs = df.corr()
figure = ff.create_annotated_heatmap(
    z=corrs.values,
    x=list(corrs.columns),
    y=list(corrs.index),
    annotation_text=corrs.round(2).values,
    showscale=True)

Cufflinks также предлагает несколько тем, которые можно использовать для получения совершенно другого стиля, не прилагая усилий. Например, ниже можно увидеть графики с темами «space» и «ggplot»

Не 2D единым:

Ну и куда без круговой диаграммы?

Редактирование в Plotly Chart Studio

В процессе создания этих графиков в блокноте можно заметить маленькую ссылку в правом нижнем углу, которая гласит «Export to plot.ly». После перехода по ней вы попадёте в редактор графиков, где вы можете внести финальные штрихи в график перед презентацией графика. Вы можете добавить аннотации, выбрать цвета и в целом сделать из графика конфетку. Затем можно опубликовать график и поделиться ссылкой на него.

Ниже показаны два графика, которые я подправил в Chart Studio:

Мы упомянули много всего, однако мы всё ещё не раскрыли весь потенциал библиотеки! Настоятельно рекомендую заглянуть в документацию plotly и cufflinks, чтобы увидеть ещё более потрясающие графики:

Интерактивный график ветряных мельниц в США (источник)

Заключение

Когда речь заходит о библиотеках для построения графиков, есть несколько вещей, которые зачастую нужны разработчику:

  1. Быстрое построение графиков в одну строку.
  2. Интерактивные элементы для получения более узкой выборки.
  3. Возможность углубиться в детали при необходимости.
  4. Простая настройка для конечной презентации.

На данный момент лучше всего для этих целей в Python подходит plotly. Plotly позволяет быстро визуализировать данные и благодаря интерактивности помогает лучше в них разобраться. И давайте начистоту — визуализация должна быть одной из самых приятных частей data science! С использованием других библиотек построение графиков превращалось в утомительное занятие, однако plotly возвращает радость от этого дела.

Смотрите также: Основы статистики с Python

Хинт для программистов: если зарегистрироваться на соревнования Huawei Honor Cup, бесплатно получите доступ к онлайн-школе для участников. Можно прокачаться по разным навыкам и выиграть призы в самом соревновании. Перейти к регистрации.