Пора перейти от теории визуализации данных к практике.
В этом параграфе мы с помощью 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()
По оси X указан год производства, а по оси Y — количество фильмов, произведённых в этот год. Как видно из этого графика, производство фильмов начало расти после восьмидесятых, причём после начала нулевых производство фильмов резко увеличилось.
Столбцы на получившейся гистограмме довольно широкие, что позволяет нам довольно примерно оценить соотношение года и количества произведённых фильмов. Однако это регулируемый параметр. По умолчанию он равен 10, но давайте удвоим количество столбцов (иначе их называют корзинами):
plt.hist(df['release_year'], bins=20)
plt.show()
Мы добавили параметр функции 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()
Обратите внимание на интересную вещь. Мы рисуем две гистограммы, но видим их не отдельно, а вместе. Дело в том, что если мы определяем две гистограммы подряд, то пакет интерпретирует это как предложение нарисовать их поверх друг друга. Это может быть полезным.
С помощью такой визуализации мы можем увидеть, как менялись темпы производства фильмов и шоу. Однако эта визуализация будет не вполне понятна для аудитории: что именно изображено на графике? Что отражает график синего и оранжевого цвета? Эти вопросы стоит прояснить, поэтому мы добавим текстовые объяснения на график.
plt.hist(df_film['release_year'], label = 'Films')
plt.hist (df_show['release_year'], label = 'Shows')
plt.legend()
plt.show()
Давайте разберём, что мы добавили на график:
- 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()
К нашему коду мы добавили строки, которые задают названия осей и графика в целом. Посмотрим теперь, как работать с категориальными переменными.
Столбчатые диаграммы
Для визуализации категориальных переменных мы будем использовать столбчатые диаграммы. Они могут внешне напоминать гистограммы, но сильно отличаются по смыслу, в первую очередь как раз тем, что используются при работе с категориальными шкалами.
Для начала посмотрим, какие возрастные категории фильмов и шоу были самыми распространёнными. В нашем наборе данных есть переменная 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
— точечная диаграмма;
В итоге получаем количество фильмов и шоу по возрастным категориям:
Мы можем отдельно оценить количество фильмов и ТВ-шоу по категориям. Опять же, начнём с кода, который покажет нам такие данные:
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. Она нужна для того, чтобы на визуализации объединить под одной категорией и фильмы, и ТВ-шоу. Чтобы лучше понять принцип работы этой функции, вы можете удалить эту часть кода и попробовать визуализировать без неё. В текущем же виде мы получим вот такую визуализацию:
Глядя на эту визуализацию, можно обнаружить, что, хотя в большинстве категорий фильмы преобладают над ТВ-шоу, есть несколько категорий, где ситуация радикально иная.
Линейные графики
Линейные графики нужны нам, когда мы визуализируем количественные показатели и их связь между собой. В нашем наборе данных один из таких показателей — это год производства фильма. Однако все остальные показатели — категориальные, поэтому нам необходимо выполнить некоторые преобразования. Например, мы можем посчитать, какое количество фильмов было произведено в каждый год.
Для этого используем следующий код:
>>> 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()
Простой, но отчётливо наблюдаемый тренд — это увеличение производства фильмов и ТВ-шоу от года к году.
Точечная диаграмма
Точечная диаграмма нужна нам для визуализации двух переменных и, как мы уже видели в предыдущем параграфе, часто используется при работе с корреляциями.
В нашем наборе данных есть две подходящие переменные: год производства и длительность фильма. Однако длительность фильма изначально представлена как строка, поскольку содержит не только данные о количестве минут или сезонов, но и текст. Это не подходит для наших задач, поэтому мы преобразуем переменную. Мы не будем подробно разбирать, как именно это сделать в 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:
- из каких элементов состоят графики и как их оформлять;
- как выбирать подходящий тип графика для наших задач;
- как создавать графики в Python с помощью библиотеки matplotlib.
Вы хорошо поработали! А новые знания сделают ваши исследования ещё убедительнее.
В следующей главе мы узнаем, как работать с опросными данными и как правильно сокращать объём данных, не теряя сути.