Пора перейти от теории визуализации данных к практике.

В этом параграфе мы с помощью Python научимся создавать графики, о которых говорили в предыдущем параграфе, — гистограммы, столбчатые диаграммы, точечные диаграммы и другие. Но для этого нам сперва нужно сказать пару слов о библиотеке matplotlib.

Общие принципы matplotlib

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

Библиотека matplotlib устанавливается и импортируется так же, как и другие библиотеки:

>>> import matplotlib.pyplot as plt

Для иллюстрации работы библиотеки matplotlib мы будем использовать датасет с информацией о контенте стриминговой платформы Disney+.

Создание визуализаций можно представить как последовательное добавление различных элементов итогового графика:

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

Гистограммы

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

import pandas as pd
df = pd.read_csv('disney_plus_titles.csv')
plt.hist(df['release_year'])
plt.show()

5

По оси X указан год производства, а по оси Y — количество фильмов, произведённых в этот год. Как видно из этого графика, производство фильмов начало расти после восьмидесятых, причём после начала нулевых производство фильмов резко увеличилось.

Столбцы на получившейся гистограмме довольно широкие, что позволяет нам довольно примерно оценить соотношение года и количества произведённых фильмов. Однако это регулируемый параметр. По умолчанию он равен 10, но давайте удвоим количество столбцов (иначе их называют корзинами):

plt.hist(df['release_year'], bins=20)
plt.show()

5

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

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

df_film = df[df['type'] == 'Movie']
df_show = df[df['type'] == 'TV Show']

Теперь добавим интересующие нас данные на график:

plt.hist(df_film['release_year'])
plt.hist(df_show['release_year'])
plt.show()

5

Обратите внимание на интересную вещь. Мы рисуем две гистограммы, но видим их не отдельно, а вместе. Дело в том, что если мы определяем две гистограммы подряд, то пакет интерпретирует это как предложение нарисовать их поверх друг друга. Это может быть полезным.

С помощью такой визуализации мы можем увидеть, как менялись темпы производства фильмов и шоу. Однако эта визуализация будет не вполне понятна для аудитории: что именно изображено на графике? Что отражает график синего и оранжевого цвета? Эти вопросы стоит прояснить, поэтому мы добавим текстовые объяснения на график.

plt.hist(df_film['release_year'], label = 'Films')
plt.hist (df_show['release_year'], label = 'Shows')
plt.legend()
plt.show()

5

Давайте разберём, что мы добавили на график:

  • label — с помощью этого параметра мы добавили подписи к гистограммам;
  • legend — с помощью этого аргумента мы выводим на график подписи к данным к ним — это не только названия данных, но и, например, названия осей и графика в целом.

Посмотрим, как добавить эти названия тоже.

plt.hist(df_film['release_year'], label = 'Films', bins = 20)
plt.hist(df_show['release_year'], label = 'Shows', bins = 20)
plt.xlabel("Year")
plt.ylabel("amount")
plt.title('Hist #1')
plt.legend()
plt.show()

5

К нашему коду мы добавили строки, которые задают названия осей и графика в целом. Посмотрим теперь, как работать с категориальными переменными.

Столбчатые диаграммы

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

Для начала посмотрим, какие возрастные категории фильмов и шоу были самыми распространёнными. В нашем наборе данных есть переменная Rating, которая отражает, какой именно возрастной рейтинг был присвоен каждому фильму и шоу. Для начала посмотрим на эти данные без визуализации. Напомним, что для этого можно использовать функцию value_counts():

>>> df['rating'].value_counts()
TV-G        318
TV-PG       301
G           253
PG          236
TV-Y7       131
TV-14        79
PG-13        66
TV-Y         50
TV-Y7-FV     13
Name: rating, dtype: int64

Так мы можем понять наиболее и наименее распространённые рейтинги. В кодбуке к набору данных (или просто в интернете) можно узнать, чему соответствует каждый рейтинг. Например, TV-G означает, что фильм подходит для всех возрастных категорий. Однако теперь попробуем визуализировать эти данные.

Для этого мы будем использовать следующую запись:

df['rating'].value_counts().plot(kind='bar', ylabel='frequency')
plt.show()

Несколько пояснений по этому коду, поскольку такой вид записи отличается от тех, что мы рассматривали ранее. Раз мы используем преобразованные данные, то код устроен следующим образом:

  • сначала мы проделываем работу с данными — это первая часть кода;
  • затем используем функцию plot() — она указывает, что полученные данные необходимо визуализировать;
  • параметры этой функции задают способ визуализации и дополнительные параметры, в нашем случае — тип графика и подпись к оси Y.

Вот ещё возможные значения параметра kind:

  • line — линейный график;
  • hist — гистограмма;
  • box — бокс-плот;
  • pie — круговая диаграмма;
  • kde — линия плотности распределения;
  • density — гибрид линейного графика и гистограммы;
  • scatter — точечная диаграмма;

В итоге получаем количество фильмов и шоу по возрастным категориям:

5

Мы можем отдельно оценить количество фильмов и ТВ-шоу по категориям. Опять же, начнём с кода, который покажет нам такие данные:

df.groupby('type')['rating'].value_counts()
type     rating
Movie    G           253
         PG          235
         TV-G        233
         TV-PG       181
         PG-13        66
         TV-14        37
         TV-Y7        36
         TV-Y7-FV      7
         TV-Y          3
TV Show  TV-PG       120
         TV-Y7        95
         TV-G         85
         TV-Y         47
         TV-14        42
         TV-Y7-FV      6
         PG            1
Name: rating, dtype: int64

Тут вас может смутить синтаксис, расскажем о нём чуть подробнее:

  • на объекте df вызываем метод groupby, передав в качестве параметра аргумент type — этот метод группирует датафрейм по переменной type;
  • он возвращает новый объект — сгруппированный датафрейм;
  • у него выбираем все значения по переменной rating;
  • и подсчитываем количество наблюдений для каждого уникального значения.

Полученные данные уже сложнее воспринимать. Рассмотрим код для визуализации этих данных:

vis_1 = df.groupby('type')['rating'].value_counts()
vis_1.unstack(0).plot(kind='bar', ylabel='frequency')

Первой строкой мы сохранили данные в преобразованном виде.

Второй строкой мы задали параметры визуализации. Все его части нам знакомы, кроме функции unstack. Она нужна для того, чтобы на визуализации объединить под одной категорией и фильмы, и ТВ-шоу. Чтобы лучше понять принцип работы этой функции, вы можете удалить эту часть кода и попробовать визуализировать без неё. В текущем же виде мы получим вот такую визуализацию:

5

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

Линейные графики

Линейные графики нужны нам, когда мы визуализируем количественные показатели и их связь между собой. В нашем наборе данных один из таких показателей — это год производства фильма. Однако все остальные показатели — категориальные, поэтому нам необходимо выполнить некоторые преобразования. Например, мы можем посчитать, какое количество фильмов было произведено в каждый год.

Для этого используем следующий код:

>>> df['release_year'].value_counts()
2021    125
2020    114
2019     99
2017     69
2018     65
       ...
1944      1
1945      1
1970      1
1968      1
1928      1
Name: release_year, Length: 90, dtype: int64

Так мы узнали, сколько фильмов было произведено в каждый год. Теперь визуализируем это соотношение. Чтобы это сделать, нам необходимо ещё одно преобразование — связь года и количества произведённых фильмов необходимо сохранить как датафрейм.

>>> film_year = pd.DataFrame(df['release_year'].value_counts().reset_index().values, columns=["Year", "amount"])
>>> film_year = film_year.sort_values('Year', ascending = True)
>>> print(film_year)
   Year  amount
89  1928       1
74  1932       3
73  1933       3
56  1934       4
57  1935       4
..   ...     ...
3   2017      69
4   2018      65
2   2019      99
1   2020     114
0   2021     125

[90 rows x 2 columns]

Этим кодом мы создали первой строкой датафрейм с колонками “Year” и “amount”, а второй строкой отсортировали его по годам. Дальнейшая визуализация будет очень простой:

plt.plot(film_year['Year'], film_year['amount'])
plt.show()

5

Простой, но отчётливо наблюдаемый тренд — это увеличение производства фильмов и ТВ-шоу от года к году.

Точечная диаграмма

Точечная диаграмма нужна нам для визуализации двух переменных и, как мы уже видели в предыдущем параграфе, часто используется при работе с корреляциями.

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

df['duration'] = df['duration'].replace('min' or 'Season', '', regex=True).apply(pd.to_numeric, errors='coerce')
df_2 = df[df['duration'] > 15]

Мы убрали текст из колонки и превратили строки в числа, а затем исключили значения меньше 15, чтобы убрать данные, касающиеся сезонов, а не фильмов.

plt.scatter(df_2['release_year'], df_2['duration'], alpha=0.5)
plt.show()

Код выглядит очень просто. Мы указываем тип визуализации, переменные по шкале X и Y, а также для прозрачности показатель alpha, с которым мы уже сталкивались.

5

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

Давайте коротко повторим, что мы узнали в главе 5:

  • из каких элементов состоят графики и как их оформлять;
  • как выбирать подходящий тип графика для наших задач;
  • как создавать графики в Python с помощью библиотеки matplotlib.

Вы хорошо поработали! А новые знания сделают ваши исследования ещё убедительнее.

В следующей главе мы узнаем, как работать с опросными данными и как правильно сокращать объём данных, не теряя сути.

Отмечайте параграфы как прочитанные чтобы видеть свой прогресс обучения

Вступайте в сообщество хендбука

Здесь можно найти единомышленников, экспертов и просто интересных собеседников. А ещё — получить помощь или поделиться знаниями.
Вступить
Сообщить об ошибке
Предыдущий параграф5.2. Типология визуализаций
Следующий параграф6.1. Опросные данные