Files
python-course-ipynb/visual.ipynb

1495 lines
49 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<!-- dom:TITLE: Графическая визуализация данных -->\n",
"# Графическая визуализация данных\n",
"<!-- dom:AUTHOR: С.В. Лемешевский Email:sergey.lemeshevsky@gmail.com at Институт математики НАН Беларуси -->\n",
"<!-- Author: --> \n",
"**С.В. Лемешевский** (email: `sergey.lemeshevsky@gmail.com`), Институт математики НАН Беларуси\n",
"\n",
"Date: **Mar 31, 2020**\n",
"\n",
"Одной из важных частей в анализе данных является графическое\n",
"визуализация. Это может быть частью исследовательского процесса —\n",
"например, чтобы помочь идентифицировать выбросы или необходимые\n",
"преобразования данных, или как способ генерирования идей для\n",
"моделей. В Python есть много дополнительных библиотек для создания\n",
"статических или динамических визуализаций, но мы сосредоточемся в\n",
"основном на `matplotlib` и библиотеках, которые построены на её\n",
"основе. \n",
"\n",
"Со временем `matplotlib` породила ряд дополнительных наборов инструментов\n",
"для визуализации данных, которые используют `matplotlib` в качестве\n",
"«ядра». Одним из таких инструментов является `seaborn`.\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"<!-- Common Mako variable and functions -->\n",
"<!-- -*- coding: utf-8 -*- -->\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Краткий пример использования `matplotlib`\n",
"<div id=\"visual:matplotlib\"></div>\n",
"\n",
"Для импорта библиотеки `matplotlib` будем использовать следующее\n",
"соглашение:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ниже приведен пример построения простой прямой:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"data = np.arange(10)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"plt.plot(data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Рисунки и подграфики\n",
"<div id=\"visual:matplotlib:figs_and_subplots\"></div>\n",
"\n",
"Графики в `matplotlib` находятся внутри объекта `Figure`. Новый\n",
"рисунок можно создать с помощью `plt.figure`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"fig = plt.figure()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В интерпретаторе IPython будет построено пустое окно, а в блокноте\n",
"Jupyter ничего не произойдет. Нельзя создавать окно с пустым\n",
"рисунком. Нужно создать один или несколько подграфиков (subplots),\n",
"используя функцию `add_subplot`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"fig.add_subplot(2, 2, 1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Это означает, что рисунок должен быть размером $2 \\times 2$\n",
"(т.е. содержать максимум 4 графика), и мы выбрали первый из четырех\n",
"графиков (нумерация начинается с единицы). Можно выбрать следующие 2\n",
"графика:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"ax2 = fig.add_subplot(2, 2, 2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"ax3 = fig.add_subplot(2, 2, 3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Если выполнить команду построения графика, например, `plt.plot([1.5, 3.5, -2, 1.6])`,\n",
"вывод будет осуществляться в последний график последнего созданного\n",
"рисунка. Например, выполнение команды"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"plt.plot(np.random.randn(50).cumsum(), 'k--')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Выражение `'k--'` задает стиль линии: черная штриховая линия. \n",
"Метод `fig.add_subplot` возвращает объект `AxesSubplot`, в который\n",
"можно напрямую выводить график:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"_ = ax1.hist(np.random.randn(100), bins=20, color='k', alpha=0.3)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Полный каталог типов графиков можно найти на сайте <https://matplotlib.org/>.\n",
"\n",
"Как вы заметили представленные выше команды, выполняемые в отдельных\n",
"ячейках, в блокноте Jupyter не работают. Для того чтобы строить\n",
"подграфики в Jupyter нужно все команды выполнять в одной ячейке:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"fig = plt.figure()\n",
"fig.add_subplot(2, 2, 1)\n",
"ax1 = fig.add_subplot(2, 2, 2)\n",
"ax2 = fig.add_subplot(2, 2, 3)\n",
"plt.plot([1.5, 3.5, -2, 1.6])\n",
"_ = ax1.hist(np.random.randn(100), bins=20, color='k', alpha=0.3)\n",
"ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Цвет, маркеры и стили линий\n",
"<div id=\"visual:matplotlib:colors\"></div>\n",
"\n",
"Основная функция `plot` библиотеки `matplotlib` принимает массивы\n",
"координат `x` и `y` и (опционально) строку, задающую цвет и стиль\n",
"линии. Например, для того чтобы построить зависимость `y` от `x`\n",
"зелеными штрихами, необходимо выполнить:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```Python\n",
" ax.plot(x, y, 'g--')\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Таким образом, мы задали и цвет и стиль линии в виде строки. На\n",
"практике при программном создании графиков использование строк не\n",
"удобно. Такой же график можно построить с помощью команды:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```Python\n",
" ax.plot(x, y, linestyle='--', color='g')\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Графики могут иметь также маркеры для выделения точек данных. Так как\n",
"`matplotlib` создает непрерывные линии, интерполируя значения между\n",
"заданными точками, может быть не ясно, где находятся заданные\n",
"значения. Маркеры могут быть частью строки, задающей стиль линии:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"from numpy.random import randn"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"plt.plot(randn(30).cumsum(), 'ko--')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Это же можно было записать более явно:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```Python\n",
" plot(randn(30).cumsum(), color='k', linestyle='dashed', marker='o')\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Как видно, между последовательными точками строится линейная\n",
"интерполяция. Это поведение можно изменить с помощью параметра\n",
"`drawstyle`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"data = np.random.randn(30).cumsum()\n",
"plt.plot(data, 'k--', label='Default')\n",
"plt.plot(data, 'k-', drawstyle='steps-post', label='steps-post')\n",
"plt.legend(loc='best')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Подписи к осям, масштаб и легенда\n",
"<div id=\"visual:matplotlib:ticks\"></div>\n",
"\n",
"Для иллюстрации настройки графиков создадим простой рисунок и\n",
"отобразим график случайного блуждания:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"fig = plt.figure()\n",
"ax = fig.add_subplot(1, 1, 1)\n",
"ax.plot(np.random.randn(1000).cumsum())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Для изменения подписей на оси $x$ воспользуемся методами `set_xticks`\n",
"и `set_xticklables`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"fig = plt.figure()\n",
"ax = fig.add_subplot(1, 1, 1)\n",
"ax.plot(np.random.randn(1000).cumsum())\n",
"ticks = ax.set_xticks([0, 250, 500, 750, 1000])\n",
"labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], rotation=30, fontsize='small')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Параметр `rotation` поворачивает метки надписей на оси $x$ на 30\n",
"градусов. И, наконец, зададим название графика и метку для оси $x$ с\n",
"помощью методов `set_title` и `set_xlabel`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"fig = plt.figure()\n",
"ax = fig.add_subplot(1, 1, 1)\n",
"ax.plot(np.random.randn(1000).cumsum())\n",
"ticks = ax.set_xticks([0, 250, 500, 750, 1000])\n",
"labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], rotation=30, fontsize='small')\n",
"ax.set_title('Первый график matplotlib')\n",
"ax.set_xlabel('Шаги')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Модификация оси $y$ осуществляется точно также, только нужно заменить\n",
"`x` на `y` в приведенном выше коде. У класса осей есть метод `set`,\n",
"который допускает пакетную настройку свойств графика. В предыдущем \n",
"примере можно было также написать:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```Python\n",
" props = {\n",
" 'title': 'Первый график matplotlib',\n",
" 'xlabel': 'Шаги\n",
" }\n",
" ax.set(**props)\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Для вывода легенды графика есть несколько способов. Простейший\n",
"заключается в передаче аргумента `label` при построении графиков:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"fig = plt.figure(); ax = fig.add_subplot(1, 1, 1)\n",
"ax.plot(randn(1000).cumsum(), 'k', label='one')\n",
"ax.plot(randn(1000).cumsum(), 'k--', label='two')\n",
"ax.plot(randn(1000).cumsum(), 'k.', label='three')\n",
"ax.legend(loc='best')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Сохранение рисунков в файл\n",
"<div id=\"visual:matplotlib:saving\"></div>\n",
"\n",
"Можно сохранить активный рисунок в файл с помощью метода\n",
"`plt.savefig`. Например, чтобы сохранить рисунок в формате SVG\n",
"достаточно набрать:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```Python\n",
" plt.savefig('figpath.svg')\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Тип файла определяется расширением. Есть пара важных параметров:\n",
"`dpi`, который задает разрешение рисунка (точек на дюйм),\n",
"`bbox_inches`, который может обрезать пустое пространство вокруг\n",
"рисунка. Например, чтобы сохранить тот же график в формате PNG с\n",
"разрешением 400 DPI, нудно выполнить:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```Python\n",
" plt.savefig('figpath.png', dpi=400, bbox_inches='tight')\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Функция `savefig` сохраняет не только на диск. Она может записывать\n",
"график в любой файлоподобный объект, например в `BytesIO`:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```Python\n",
" from io import BytesIO\n",
" buffer = BytesIO()\n",
" plt.savefig(buffer)\n",
" plot_data = buffer.getvalue()\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Таблица 1 : Метод `savefig`: параметры\n",
"\n",
"\n",
"<table border=\"1\">\n",
"<thead>\n",
"<tr><th align=\"left\"> Параметр </th> <th align=\"left\"> Описание </th> </tr>\n",
"</thead>\n",
"<tbody>\n",
"<tr><td align=\"left\"> <code>fname</code> </td> <td align=\"left\"> Строка, содержащая путь к файлу или файлоподобный объект Python. Формат рисунка определяется расширением файла </td> </tr>\n",
"<tr><td align=\"left\"> <code>dpi</code> </td> <td align=\"left\"> Разрешение рисунка в точках на дюйм. По умолчанию 100 </td> </tr>\n",
"<tr><td align=\"left\"> <code>facecolor</code>, <code>edgecolor</code> </td> <td align=\"left\"> Цвет фона рисунка вне графика. По умолчанию <code>w</code> (белый) </td> </tr>\n",
"<tr><td align=\"left\"> <code>format</code> </td> <td align=\"left\"> Явное задание формата файла </td> </tr>\n",
"<tr><td align=\"left\"> <code>bbox_inches</code> </td> <td align=\"left\"> Часть рисунка для сохранения. Если задано <code>'tight'</code>, 2будет попытка обрезать пустое пространство вокруг </td> </tr>\n",
"</tbody>\n",
"</table>\n",
"\n",
"\n",
"\n",
"\n",
"<!-- Local Variables: -->\n",
"<!-- doconce-chapter-nickname: \"visual\" -->\n",
"<!-- doconce-section-nickname: \"matplotlib\" -->\n",
"<!-- End: -->\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Построение графиков с помощью `pandas` и `seaborn`\n",
"<div id=\"visual:plt-with-pandas\"></div>\n",
"\n",
"Библиотека `matplotlib` может быть инструментом довольно низкого\n",
"уровня. График собирается из его базовых компонентов: отображения\n",
"данных (т.е. тип графика: линия, полоса, прямоугольник, разброс,\n",
"контур и т.д.), легенды, заголовка, меток и других аннотаций. В\n",
"библиотеке `pandas` мы можем получить множество столбцов данных, а\n",
"также метки строк и столбцов. В `pandas` имеются встроенные методы,\n",
"которые упрощают визуализацию объектов `DataFrame` и `Series`. Еще\n",
"одна библиотека для статистических графиков — `seaborn`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Линейные графики\n",
"<div id=\"visual:plt-with-pandas:line\"></div>\n",
"\n",
"Объекты `Series` и `DataFrame` имеют метод `plot` для создания базовых\n",
"типов графиков. По умолчанию `plot()` создает линейные графики"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"s = pd.Series(np.random.randn(10).cumsum(), index=np.arange(0, 100, 10))\n",
"s.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Индекс объекта `Series` передается в `plot` библиотеки `matplotlib`\n",
"для оси $x$. При этом такое поведение можно отключить с помощью\n",
"параметра `use_index = False`. В таблице\n",
"[visual:plt-with-pandas:tbl:1](#visual:plt-with-pandas:tbl:1) дается полный список\n",
"параметров функции `Series.plot`.\n",
"\n",
"Большинство графических методов `pandas` принимают опциональный\n",
"параметр `ax`, который может являться объектом `subplot`. Это\n",
"позволяет размещать подграфики на сетке.\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Таблица 2 : Параметры метода `Series.plot` <div id=\"visual:plt-with-pandas:tbl:1\"></div>\n",
"\n",
"\n",
"<table border=\"1\">\n",
"<thead>\n",
"<tr><th align=\"left\"> Параметр </th> <th align=\"left\"> Описани </th> </tr>\n",
"</thead>\n",
"<tbody>\n",
"<tr><td align=\"left\"> <code>label</code> </td> <td align=\"left\"> Метка для легенды </td> </tr>\n",
"<tr><td align=\"left\"> <code>ax</code> </td> <td align=\"left\"> Объект <code>subplot</code> из <code>matplotlib</code>, в который выводится график. Если не задан — вывод идет в активный подграфик </td> </tr>\n",
"<tr><td align=\"left\"> <code>style</code> </td> <td align=\"left\"> Строка, задающая стиль графика (например, <code>ko--</code>) </td> </tr>\n",
"<tr><td align=\"left\"> <code>alpha</code> </td> <td align=\"left\"> Прозрачность заполнения графика (от 0 до 1) </td> </tr>\n",
"<tr><td align=\"left\"> <code>kind</code> </td> <td align=\"left\"> Тип графика. Может быть: 'area' , 'bar' , 'barh' , 'density', 'hist' , 'kde' , 'line' , 'pie' </td> </tr>\n",
"<tr><td align=\"left\"> <code>logy</code> </td> <td align=\"left\"> Использовать ли логарифмический масштаб по оси <code>y</code> </td> </tr>\n",
"<tr><td align=\"left\"> <code>use_index</code> </td> <td align=\"left\"> Использовать ли объект индекс для меток оси </td> </tr>\n",
"<tr><td align=\"left\"> <code>rot</code> </td> <td align=\"left\"> Поворот меток оси </td> </tr>\n",
"<tr><td align=\"left\"> <code>xticks</code> </td> <td align=\"left\"> Значения для меток оси <code>x</code> </td> </tr>\n",
"<tr><td align=\"left\"> <code>yticks</code> </td> <td align=\"left\"> Значения для меток оси <code>x</code> </td> </tr>\n",
"<tr><td align=\"left\"> <code>xlim</code> </td> <td align=\"left\"> Границы по оси <code>x</code> (например, <code>[0, 10]</code>) </td> </tr>\n",
"<tr><td align=\"left\"> <code>ylim</code> </td> <td align=\"left\"> Границы по оси <code>y</code> </td> </tr>\n",
"<tr><td align=\"left\"> <code>grid</code> </td> <td align=\"left\"> Отображать ли сетку по осям (включено по умолчанию) </td> </tr>\n",
"</tbody>\n",
"</table>\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Метод `plot` объекта `DataFrame` выводит график для каждого столбца\n",
"данных в виде линии на одном и том же подграфике, создавая при этом\n",
"легенду автоматически:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"df = pd.DataFrame(np.random.randn(10, 4).cumsum(0), columns=['A', 'B', 'C', 'D'], index=np.arange(0, 100, 10))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"df.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Атрибут `plot` содержит «семейство» методов для различных типов\n",
"графиков. Например, `df.plot()` эквивалентно `df.plot.line()`.\n",
"\n",
"В `DataFrame` есть несколько параметры, которые обеспечивают некоторую\n",
"гибкость при обработке столбцов. Например, следует ли разместить их\n",
"все на одном подграфике или создавать отдельные. В таблице\n",
"[visual:plt-with-pandas:tbl:2](#visual:plt-with-pandas:tbl:2) представлены такие параметры.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Таблица 3 : Специфичные для `DataFrame` параметры `plot` <div id=\"visual:plt-with-pandas:tbl:2\"></div>\n",
"\n",
"\n",
"<table border=\"1\">\n",
"<thead>\n",
"<tr><th align=\"left\"> Параметр </th> <th align=\"left\"> Описание </th> </tr>\n",
"</thead>\n",
"<tbody>\n",
"<tr><td align=\"left\"> <code>subplots</code> </td> <td align=\"left\"> Рисовать ли каждый столбец <code>DataFrame</code> в отдельном подграфике </td> </tr>\n",
"<tr><td align=\"left\"> <code>sharex</code> </td> <td align=\"left\"> Если <code>subplots=True</code>, использовать ли одну и ту же ось <code>x</code>, связывая метки оси </td> </tr>\n",
"<tr><td align=\"left\"> <code>sharey</code> </td> <td align=\"left\"> Если <code>subplots=True</code>, использовать ли одну и ту же ось <code>y</code> </td> </tr>\n",
"<tr><td align=\"left\"> <code>figsize</code> </td> <td align=\"left\"> Размер рисунка для создания в виде кортежа </td> </tr>\n",
"<tr><td align=\"left\"> <code>title</code> </td> <td align=\"left\"> Заголовок рисунка в виде строки </td> </tr>\n",
"<tr><td align=\"left\"> <code>legend</code> </td> <td align=\"left\"> Добавлять ли легенду на рисунок (по умолчанию <code>True</code>) </td> </tr>\n",
"<tr><td align=\"left\"> <code>sort_columns</code> </td> <td align=\"left\"> Отображать ли столбцы в алфавитном порядке </td> </tr>\n",
"</tbody>\n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Столбчатые диаграммы\n",
"<div id=\"visual:plt-with-pandas:bar\"></div>\n",
"\n",
"Методы `plot.bar()` и `plot.barh()` строят вертикальные и\n",
"горизонтальные столбчатые диаграммы. В этом случае индексы объектов\n",
"`Series` и `DataFrame` в качестве меток на оси `x` (`bar`) или `y`\n",
"(`barh`)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"fig, axes = plt.subplots(2, 1)\n",
"data = pd.Series(np.random.rand(16), index=list('abcdefghijklmnop'))\n",
"data.plot.bar(ax=axes[0], color='k', alpha=0.7)\n",
"data.plot.barh(ax=axes[1], color='k', alpha=0.7)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Параметры `color='k`' и `alpha=0.7` устанавливают цвет графика в\n",
"черный и частичную прозрачность для заполнения.\n",
"\n",
"В `DataFrame` столбчатые диаграммы группируют каждую строку значений\n",
"вместе в группу столбиков, соответствующих каждому значению в строке:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"df = pd.DataFrame(np.random.rand(6, 4), index=['one', 'two', 'three', 'four', 'five', 'six'], columns=pd.Index(['A', 'B', 'C', 'D'], name='Genus'))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"df"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"df.plot.bar()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обратите внимание на то, что имя столбцов `'Genus'` используется в\n",
"качестве заголовка легенды. Для создания столбчатых диаграмм с\n",
"накоплением для `DataFrame` задается параметр `stacked=True`, в\n",
"результате чего значение в каждой строке будут сгруппировано вместе"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"df.plot.barh(stacked=True, alpha=0.5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Предположим, что есть набор данных по счетам и чаевым в ресторане, и\n",
"нам нужно построить столбчатую диаграмму с накоплением, показывающую\n",
"процентное соотношение точек данных для каждого размера группы в\n",
"каждый день. Загрузим данные из файла\n",
"[tips.csv](src-visual/tips.csv.txt) и создадим сводную по дням и размеру вечеринки\n",
"(количество человек):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"tips = pd.read_csv('src-visual/tips.csv')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"tips.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"party_counts = pd.crosstab(tips['day'], tips['size'])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"party_counts"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"party_counts = party_counts.loc[:, 2:5]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Теперь нормализуем данные так, чтобы сумма в каждой строке была равна\n",
"$1$ и построим столбчатую диаграмму:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"party_pcts = party_counts.div(party_counts.sum(1), axis=0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"party_pcts"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"party_pcts.plot.bar()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Таким образом, видно, что количество участников вечеринок\n",
"в данном наборе увеличивается в выходные дни.\n",
"\n",
"В случае, если требуется агрегировать или суммировать данные перед\n",
"построением графика, использование пакета `seaborn` может значительно\n",
"упростить задачу. Давайте посмотрим на процент чаевых в день с помощью\n",
"библиотеки `seaborn`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"import seaborn as sns"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"tips['tip_pct'] = tips['tip']/(tips['total_bill'] - tips['tip'])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"tips.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"sns.barplot(x='tip_pct', y='day', data=tips, orient='h')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Функция `barplot` библиотеки `seaborn` принимает параметр `data`, который\n",
"может быть объектом `DataFrame`. Остальные параметры ссылаются на\n",
"имена столбцов. Поскольку в день имеется несколько наблюдений, то\n",
"столбцы диаграммы представляют собой среднее значение параметра\n",
"`tip_pct`. Черные линии, нарисованные на столбцах диаграммы,\n",
"представляют 95-процентный доверительный интервал (это можно настроить\n",
"с помощью опционального параметра). \n",
"\n",
"Функция `barplot` имеет параметр `hue`, который позволяет разделить\n",
"отображение по дополнительному категориальному значению:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"sns.barplot(x='tip_pct', y='day', hue='time', data=tips, orient='h')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Гистограммы и графики плотности распределения\n",
"<div id=\"visual:plt-with-pandas:hist\"></div>\n",
"\n",
"*Гистограмма* — это своего рода столбчатая диаграмма, которая дает\n",
"дискретное отображение частоты значений. Составим гистограмму\n",
"процентных долей от общего счета, используя метод `plot.hist` объекта\n",
"`Series`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"tips['tip_pct'].plot.hist(bins=50)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Связанный с гистограммой тип графиков — *график плотности*, \n",
"который формируется путем вычисления оценки непрерывного распределения\n",
"вероятности, которое могло бы генерироваться наблюдаемыми данными.\n",
"Обычная процедура заключается в аппроксимации этого распределение как\n",
"смеси «ядер», то есть более простых распределений, таких как нормальное\n",
"распределение. Таким образом, графики под графиками плотности также\n",
"можно понимать графики оценки плотности ядра\n",
"(*K*ernel *D*ensity *E*stimate). Функции `plot.kde` и `plot.density`\n",
"строят график плотности, используя подход KDE:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"tips['tip_pct'].plot.kde()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Библиотека `seaborn` упрощает создание гистограмм и графиков плотности\n",
"с помощью метода `distplot`, который позволяет одновременно строить как\n",
"гистограмму, так и непрерывную оценку плотности. В качестве примера\n",
"рассмотрим бимодальное распределение, состоящее из двух разных\n",
"стандартных нормальных распределений:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"comp1 = np.random.normal(0, 1, size=200)\n",
"comp2 = np.random.normal(10, 2, size=200)\n",
"values = pd.Series(np.concatenate([comp1, comp2]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"sns.distplot(values, bins=100, color='k')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Диаграммы рассеяния или точечные графики\n",
"<div id=\"visual:plt-with-pandas:scatter\"></div>\n",
"\n",
"Диаграммы рассеяния полезны при изучении связей между двумя одномерными\n",
"рядами данных. Например, загрузим набор данных из файла\n",
"[macrodata.csv](src-visual/macrodata.csv.txt) проекта\n",
"[Statmodels](https://www.statsmodels.org/stable/index.html). Выберем\n",
"некоторые переменные и вычислим «логарифмические разности»:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"macro = pd.read_csv('src-visual/macrodata.csv')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"data = macro[['cpi', 'm1', 'tbilrate', 'unemp']]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"trans_data = np.log(data).diff().dropna()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"trans_data[-5:]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Теперь воспользуемся функцией `regplot` библиотеки `seaborn`, которая\n",
"строит графики рассеяния и предлагает график линейной регрессии:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"sns.regplot('m1', 'unemp', data=trans_data)\n",
"plt.title('Зависимость $\\log$ {} от $\\log$ {}'.format('m1', 'unemp'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"При анализе данных полезно иметь возможность просматривать все\n",
"диаграммы рассеяния среди группы переменных, т.е. строить, так\n",
"называемые, *парные графики* или *матрицу диаграмм рассеяния*. В\n",
"библиотеке `seaborn` для этого есть удобная функция `pairplot`,\n",
"которая, в частности, поддерживает размещение гистограмм или оценок\n",
"плотности каждой переменной по диагонали:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"sns.pairplot(trans_data, diag_kind='kde', plot_kws={'alpha': 0.2})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Категориальные данные\n",
"<div id=\"visual:plt-with-pandas:facet-grids\"></div>\n",
"\n",
"Одним из способов визуализации данных с множеством категориальных\n",
"переменных является использование сетки фасетов (*facet grid*). В\n",
"библиотеке `seaborn` есть удобная функция `catplot`, которая\n",
"упрощает создание сетки фасетов:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"sns.catplot(x='day', y='tip_pct', hue='time', col='smoker', kind='bar', data=tips[tips.tip_pct < 1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Вместо отображения разными цветами столбцов диаграмм в фасете мы\n",
"также можем расширить сетку фасетов, добавив одну строку по времени:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"sns.catplot(x='day', y='tip_pct', row='time', col='smoker', kind='bar', data=tips[tips.tip_pct < 1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Функция `catplot` поддерживает другие типы графиков, которые могут быть\n",
"полезны. Например, блочные графики, которые показывают медиану,\n",
"квартили и выбросы:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"sns.catplot(x='tip_pct', y='day', kind='box', data=tips[tips.tip_pct < 0.5])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Можно создавать свои собственные сетки фасетов,\n",
"используя более общий класс `seaborn.FacetGrid` (см.\n",
"[документацию seaborn](https://seaborn.pydata.org/)).\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"<!-- Local Variables: -->\n",
"<!-- doconce-chapter-nickname: \"visual\" -->\n",
"<!-- doconce-section-nickname: \"plt-with-pandas\" -->\n",
"<!-- End: -->\n",
"\n",
"\n",
"\n",
"\n",
"<!-- Local Variables: -->\n",
"<!-- doconce-chapter-nickname: \"visual\" -->\n",
"<!-- End: -->"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}