diff --git a/fig-visual/matplotlib_1.png b/fig-visual/matplotlib_1.png
new file mode 100644
index 0000000..8a3b4d2
Binary files /dev/null and b/fig-visual/matplotlib_1.png differ
diff --git a/fig-visual/matplotlib_2.png b/fig-visual/matplotlib_2.png
new file mode 100644
index 0000000..c7d0d34
Binary files /dev/null and b/fig-visual/matplotlib_2.png differ
diff --git a/fig-visual/matplotlib_3.png b/fig-visual/matplotlib_3.png
new file mode 100644
index 0000000..5ae7a3f
Binary files /dev/null and b/fig-visual/matplotlib_3.png differ
diff --git a/fig-visual/matplotlib_4.png b/fig-visual/matplotlib_4.png
new file mode 100644
index 0000000..150e17e
Binary files /dev/null and b/fig-visual/matplotlib_4.png differ
diff --git a/fig-visual/matplotlib_5.png b/fig-visual/matplotlib_5.png
new file mode 100644
index 0000000..680eaa6
Binary files /dev/null and b/fig-visual/matplotlib_5.png differ
diff --git a/fig-visual/matplotlib_6.png b/fig-visual/matplotlib_6.png
new file mode 100644
index 0000000..070ee54
Binary files /dev/null and b/fig-visual/matplotlib_6.png differ
diff --git a/fig-visual/matplotlib_7.png b/fig-visual/matplotlib_7.png
new file mode 100644
index 0000000..acbd7d3
Binary files /dev/null and b/fig-visual/matplotlib_7.png differ
diff --git a/fig-visual/matplotlib_8.png b/fig-visual/matplotlib_8.png
new file mode 100644
index 0000000..d70ba96
Binary files /dev/null and b/fig-visual/matplotlib_8.png differ
diff --git a/fig-visual/matplotlib_9.png b/fig-visual/matplotlib_9.png
new file mode 100644
index 0000000..31919c1
Binary files /dev/null and b/fig-visual/matplotlib_9.png differ
diff --git a/fig-visual/pandas-plot_1.png b/fig-visual/pandas-plot_1.png
new file mode 100644
index 0000000..07dcf9a
Binary files /dev/null and b/fig-visual/pandas-plot_1.png differ
diff --git a/fig-visual/pandas-plot_10.png b/fig-visual/pandas-plot_10.png
new file mode 100644
index 0000000..265d49c
Binary files /dev/null and b/fig-visual/pandas-plot_10.png differ
diff --git a/fig-visual/pandas-plot_11.png b/fig-visual/pandas-plot_11.png
new file mode 100644
index 0000000..831ddd1
Binary files /dev/null and b/fig-visual/pandas-plot_11.png differ
diff --git a/fig-visual/pandas-plot_12.png b/fig-visual/pandas-plot_12.png
new file mode 100644
index 0000000..37187f6
Binary files /dev/null and b/fig-visual/pandas-plot_12.png differ
diff --git a/fig-visual/pandas-plot_13.png b/fig-visual/pandas-plot_13.png
new file mode 100644
index 0000000..87482ef
Binary files /dev/null and b/fig-visual/pandas-plot_13.png differ
diff --git a/fig-visual/pandas-plot_14.png b/fig-visual/pandas-plot_14.png
new file mode 100644
index 0000000..1785437
Binary files /dev/null and b/fig-visual/pandas-plot_14.png differ
diff --git a/fig-visual/pandas-plot_15.png b/fig-visual/pandas-plot_15.png
new file mode 100644
index 0000000..026f53f
Binary files /dev/null and b/fig-visual/pandas-plot_15.png differ
diff --git a/fig-visual/pandas-plot_16.png b/fig-visual/pandas-plot_16.png
new file mode 100644
index 0000000..17551fa
Binary files /dev/null and b/fig-visual/pandas-plot_16.png differ
diff --git a/fig-visual/pandas-plot_2.png b/fig-visual/pandas-plot_2.png
new file mode 100644
index 0000000..b1e9c39
Binary files /dev/null and b/fig-visual/pandas-plot_2.png differ
diff --git a/fig-visual/pandas-plot_3.png b/fig-visual/pandas-plot_3.png
new file mode 100644
index 0000000..8d7a4f6
Binary files /dev/null and b/fig-visual/pandas-plot_3.png differ
diff --git a/fig-visual/pandas-plot_4.png b/fig-visual/pandas-plot_4.png
new file mode 100644
index 0000000..bbcf7d8
Binary files /dev/null and b/fig-visual/pandas-plot_4.png differ
diff --git a/fig-visual/pandas-plot_5.png b/fig-visual/pandas-plot_5.png
new file mode 100644
index 0000000..e554cf8
Binary files /dev/null and b/fig-visual/pandas-plot_5.png differ
diff --git a/fig-visual/pandas-plot_6.png b/fig-visual/pandas-plot_6.png
new file mode 100644
index 0000000..c2638ac
Binary files /dev/null and b/fig-visual/pandas-plot_6.png differ
diff --git a/fig-visual/pandas-plot_7.png b/fig-visual/pandas-plot_7.png
new file mode 100644
index 0000000..602dcb4
Binary files /dev/null and b/fig-visual/pandas-plot_7.png differ
diff --git a/fig-visual/pandas-plot_8.png b/fig-visual/pandas-plot_8.png
new file mode 100644
index 0000000..f4d7258
Binary files /dev/null and b/fig-visual/pandas-plot_8.png differ
diff --git a/fig-visual/pandas-plot_9.png b/fig-visual/pandas-plot_9.png
new file mode 100644
index 0000000..49624f7
Binary files /dev/null and b/fig-visual/pandas-plot_9.png differ
diff --git a/pandas.ipynb b/pandas.ipynb
new file mode 100644
index 0000000..e520947
--- /dev/null
+++ b/pandas.ipynb
@@ -0,0 +1,4235 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "# Введение в библиотеку `pandas`\n",
+ "\n",
+ " \n",
+ "**С.В. Лемешевский** (email: `sergey.lemeshevsky@gmail.com`), Институт математики НАН Беларуси\n",
+ "\n",
+ "Date: **Mar 31, 2020**\n",
+ "\n",
+ "Библиотека `pandas` содержит структуры данных и инструменты\n",
+ "управления данными, предназначенные для очистки данных и быстрого и\n",
+ "простого анализа данных в Python. Библиотека `pandas` часто\n",
+ "используется в тандеме с инструментами для численных расчетов, такими\n",
+ "как NumPy и SciPy, библиотеками для анализа данных, такими как\n",
+ "`statmodels` и `scikit-learn`, и библиотеками для визуализации, такими\n",
+ "как `matplotlib`.\n",
+ "\n",
+ "Ниже будем использовать следующее соглашение для импорта библиотеки\n",
+ "`pandas`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Структуры данных в `pandas`\n",
+ "
\n",
+ "\n",
+ "Чтобы начать работать с `pandas`, рассмотрим две основные структуры:\n",
+ "`Series` и `DataFrame`. Они не являются универсальными решениями любых\n",
+ "задач, однако эти структуры предоставляют прочный легкий в\n",
+ "использовании фундамент для большинства приложений."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Класс `Series`\n",
+ "\n",
+ "\n",
+ "`Series` (*ряд*) — объект, типа одномерного массива, содержащий\n",
+ "последовательность значений (типов, аналогичных типам NumPy) и\n",
+ "связанный с ним массив меток данных,\n",
+ "называемых *индексами*. Создадим простейший объект типа `Series`\n",
+ "только из массива данных:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series([4, 7, -5, 3])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Строковое представление объекта `Series` в интерактивном режиме\n",
+ "отображает индексы слева, а данные справа. Так как мы не определили\n",
+ "индексы, то по умолчанию индексы содержат целые числа от `0` до `N-1`\n",
+ "(где `N` — длина массива данных). Можно получить представление в виде\n",
+ "массива и индексы ряда с помощью атрибутов `values` и `index`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.values"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.index"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Часто желательно создать ряд с индексами, идентифицирующими каждую\n",
+ "точку данный с меткой:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2.index"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В отличие от массивов NumPy, можно использовать метки при индексации\n",
+ "при выборе отдельных значений или набора значений:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2['a']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2['d'] = 6"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2[['c', 'a', 'd']]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Использование функций NumPy или операций подобных NumPy, таких как\n",
+ "фильтрация с помощью булевых массивов, умножение на скаляр или\n",
+ "вычисление математических функций, сохраняет значения индексов:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2[obj2 > 0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2 * 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "np.exp(obj2)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Ряды можно рассматривать как словари фиксированной длины:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "'b' in obj2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "'e' in obj2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Если имеются данные, содержащиеся в словаре, можно создать ряд из\n",
+ "него:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj3 = pd.Series(sdata)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj3"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Если передается только словарь, то индексами ряда будут ключи словаря\n",
+ "в том порядке, в котором были при создании словаря. Можно изменить\n",
+ "порядок индекса передавая ключи словаря в порядке, который нужен:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "states = ['California', 'Ohio', 'Oregon', 'Texas']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj4 = pd.Series(sdata, index=states)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj4"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Здесь три значения, найденные в `sdata`, были размещены в\n",
+ "соответствующих местах, но так как не было найдено значение для\n",
+ "`'California'`, оно отображается как `NaN` (не число), которое в\n",
+ "`pandas` используется для обозначение пропущенных значений или\n",
+ "значений «NA» (*not available*). Поскольку `'Юта'` не была включена в `states`,\n",
+ "этот элемент исключается из результирующего объекта. Функции `isnull`\n",
+ "и `notnull` в `pandas` используются для обнаружения отсутствующих\n",
+ "данных:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "pd.isnull(obj4)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "pd.notnull(obj4)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Класс `Series` также имеет эти методы:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj4.isnull()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Полезное свойство `Series` заключается в том, что она автоматически\n",
+ "происходит выравнивание по индексам в арифметических операциях:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj3 + obj4"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Как объекты `Series`, так и из индексы имеют атрибут `name`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj4.name = 'population'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj4.index.name = 'state'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj4"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Можно изменять индексы рядов присваиванием:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Класс `DataFrame`\n",
+ "\n",
+ "\n",
+ "`DataFrame` представляет собой прямоугольную таблицу данных и содержит\n",
+ "упорядоченную коллекцию столбцов, каждый из которых может иметь\n",
+ "различный тип значения (числовой, строковый, логический и\n",
+ "т.д.). `DataFrame` имеет индексы столбцов и строк.\n",
+ "\n",
+ "Есть много способов создания объекта `DataFrame`, хотя один из\n",
+ "наиболее распространенных — это использование списков, словарей или\n",
+ "массивов NumPy:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],\n",
+ " 'year': [2000, 2001, 2002, 2001, 2002, 2003], \n",
+ " 'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame = pd.DataFrame(data)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Полученный в результате `DataFrame` получит автоматически индексацию\n",
+ "для строк (как в `Series`), а индексом столбцов будут ключи словаря:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Если используется блокнот Jupyter, объекты `DataFrame` будут\n",
+ "отображаться в виде более удобной для просмотра HTML-таблицы.\n",
+ "\n",
+ "Для больших DataFrames метод head выбирает только первые пять строк:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.head()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Можно задавать другой порядок столбцов:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "pd.DataFrame(data, columns=['year', 'state', 'pop'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Если передать столбец, который не содержится в словаре, то в\n",
+ "результате будет столбец с отсутствующими значениями:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'], index=['one', 'two', 'three', 'four', 'five', 'six'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2.columns"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "К столбцу `DataFrame` можно получить доступ как к ряду с помощью\n",
+ "нотацией подобной словарю или через атрибут:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2['state']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2.year"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> **Замечание.**\n",
+ ">\n",
+ "> IPython предоставлет доступ по атрибуту (например, `frame2.year`) \n",
+ "> по автодополнению с помощью клавиши .\n",
+ "> \n",
+ "> Вариант `frame2[column]` работает для любых имен столбцов, в то время\n",
+ "> как `frame2.column` работает только если имя столбца является\n",
+ "> допустимым в Python именем переменной.\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "К строкам можно получить доступ по позиции или с помощью специального\n",
+ "атрибута `loc`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2.loc['three']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Можно менять значения столбцов. Например, пустой столбцу `debt` можно\n",
+ "присвоить скалярное значение или массив:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2['debt'] = 16.5"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2['debt'] = np.arange(6.)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "При присваивании столбцу списка или массива, их длина должна быть той\n",
+ "же, что и длина `DataFrame`. Если присваивать объект `Series`, то его\n",
+ "метки будут выровнены по индексу `DataFrame`, при этом будут\n",
+ "вставляться отсутствующие значения для любых «дыр»:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2['debt'] = val"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "При присваивании отсутствующего столбца в объекте `DataFrame`\n",
+ "добавится новый столбец. Ключевое слово `del` удаляет столбец, как и\n",
+ "для словарей:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2['eastern'] = frame2.state == 'Ohio'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> **Предупреждение.**\n",
+ ">\n",
+ "> Новый столбец не может быть добавлен с помощью синтаксиса `frame2.eastern`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "del frame2['eastern']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2.columns"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> **Предупреждение.**\n",
+ ">\n",
+ "> Столбец, возвращаемый при индексации `DataFrame`, является\n",
+ "> представлением данных, а не копией. Таким образом, любые\n",
+ "> изменения в объекте `Series` будут отражены в объекте\n",
+ "> `DataFrame`. Столбец можно явно скопировать с помощью метода\n",
+ "> `Series.copy`.\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "Другой распространенной формой представления данных является вложенный\n",
+ "словарь словарей:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "pop = {'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Если вложенный словарь передать в конструктор `DataFrame`, `pandas`\n",
+ "интерпретирует ключи внешнего словаря как столбцы, а внутренние ключи\n",
+ "— как индексы:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame3 = pd.DataFrame(pop)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame3"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Можно транспонировать `DataFrame`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame3.T"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Можно задать порядок индексов:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "pd.DataFrame(pop, index=[2001, 2002, 2003])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Словари рядов обрабатываются практически также:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "pdata = {'Ohio': frame3['Ohio'][:-1], 'Nevada': frame3['Nevada'][:2]}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "pd.DataFrame(pdata)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Полный список параметров, которые можно передавать в конструктор\n",
+ "`DataFrame`, можно найти в таблице [pandas:data-struct:tbl:1](#pandas:data-struct:tbl:1).\n",
+ "\n",
+ "Если для индекса и столбцов DataFrame установлены атрибуты `name`, они\n",
+ "также будут отображены:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame3.index.name = 'year'; frame3.columns.name = 'state'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame3"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Как и в случае `Series`, атрибут `values` возвращает данные,\n",
+ "содержащиеся в `DataFrame`, в виде двумерного массива:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame3.values"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Таблица 1 : Возможные входные данные для конструктора `DataFrame` \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Тип | Примечания |
\n",
+ "\n",
+ "\n",
+ " Двумерный ndarray | Матрица данных, передающаяся с необязательными метками строк и столбцов |
\n",
+ " dict массивов, list, tuple | Каждая последовательность становится столбцом в DataFrame. Все последовательности должны быть одинаковой длины |
\n",
+ "| Структурированный массив (или массив записей) NumPy | Обрабатывается как предыдущий случай |
\n",
+ " dict объектов типа Series | Каждое значение становится столбцом. Индексы из каждой серии объединяются вместе, чтобы сформировать индекс строки результата, если не передан явный индекс |
\n",
+ " dict объектов типа dict | Каждый внутренний словарь становится столбцом. Ключи объединяются для формирования индекса строки, как в предыдущем случае |
\n",
+ " list объектов dict или Series | Каждый элемент становится строкой в DataFrame. Оббъединение ключей dict или индексов Series становится метками столбцов DataFrame |
\n",
+ " list объектов list или tuple | Обрабатывается как случай двумерного массива |
\n",
+ " DataFrame | Используются индексы DataFrame , если не переданы другие |
\n",
+ "| маскированный массив NumPy | Как случай двумерного массива, за исключением того, что маскированные значения становятся пропущенными (NA) значениями в итоговом DataFrame |
\n",
+ "\n",
+ "
\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Объекты типа `Index`\n",
+ "\n",
+ "\n",
+ "Объекты типа `Index` в `pandas` отвечают за хранение меток осей и\n",
+ "других метаданных (таких как имя или имя оси). \n",
+ "\n",
+ "Любой массив или другая последовательность меток, которые используются\n",
+ "при создании `Series` или `DataFrame`, преобразуется в `Index`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series(range(3), index=['a', 'b', 'c'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "index = obj.index"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "index"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "index[1:]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Объекты `Index` — неизменяемый тип и не может изменяться\n",
+ "пользователем:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "index[1] = 'd'"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Неизменяемость делает более безопасным совместное использование объектов\n",
+ "`Index`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "labels = pd.Index(np.arange(3))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "labels"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2 = pd.Series([1.5, -2.5, 0], index=lables)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2.index is lables"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "С объектами `Index` можно работать как с массивами фиксированного\n",
+ "размера:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame3.columns"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "'Ohio' in frame3.columns"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "2003 in frame3.index"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В отличие от множеств Python объекты `Index` могут содержать\n",
+ "повторяющиеся метки:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "dup_labels"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Каждый объект `Index` имеет ряд методов и свойств. Некоторые полезные\n",
+ "из них приведены в таблице [pandas:data-struct:tbl:2](#pandas:data-struct:tbl:2). "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Таблица 2 : Некоторые методы и свойства `Index` \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Метод | Описание |
\n",
+ "\n",
+ "\n",
+ " append | Добавляет дополнительные объекты Index, создавая новый объект Index |
\n",
+ " difference | Возвращает разность множеств как Index |
\n",
+ " intersection | Возвращает пересечение множеств |
\n",
+ " union | Возвращает объединение множеств |
\n",
+ " isin | Возвращает логический массив, указывающий, содержится ли каждое значение в переданной коллекции |
\n",
+ " delete | Возвращает новый объект Index с удаленным элементом по индексу i |
\n",
+ " drop | Возвращает новый объект Index, удаляя переданные значения |
\n",
+ " insert | Возвращает новый объект Index, вставляя по индексу i элемент |
\n",
+ " is_monotonic | Возвращает True, если каждый элемент больше либо равен предыдущего |
\n",
+ " is_unique | Возвращает True, если объект Index не содержит дупликатов |
\n",
+ " unique | Возвращает массив уникальных занчений в объекте Index |
\n",
+ "\n",
+ "
\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Основная функциональность\n",
+ "\n",
+ "\n",
+ "Приведем основные подходы к работе с данными, содержащимися в `Series`\n",
+ "и `DataFrame`."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Переиндексация\n",
+ "\n",
+ "\n",
+ "Важный метод в объектах `pandas` — это `reindex`, который создает\n",
+ "новый объект с данными, согласованными с новым индексом. Рассмотрим\n",
+ "пример:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Вызов `reindex` в объекте `Series` переупорядочивает данные в\n",
+ "соответствии с новым индексом, вводя пропущенные значения, если\n",
+ "какие-либо значения индекса еще не присутствовали:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "ля упорядоченных данных, таких как временные ряды, может быть\n",
+ "желательно выполнить некоторую интерполяцию или заполнение значений\n",
+ "при переиндексации. Аргумент `method` позволяет нам сделать это,\n",
+ "используя метод такой как `ffill` (forward-fill), который заполняет\n",
+ "«вперед» значениями ряд:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj3.reindex(range(6), method='ffill')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В объектах `DataFrame` метод `reindex` может изменять либо индекс\n",
+ "(строки), столбцы, либо и то и то. Когда передается только одна\n",
+ "последовательность, то переиндексируются строки:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame = pd.DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], columns=['Ohio', 'Texas', 'California'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2 = frame.reindex(['a', 'b', 'c', 'd'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Столбцы переиндексируются с помощью аргумента `columns`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "states = ['Texas', 'Utah', 'California']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.reindex(columns=states)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В таблице [pandas:functionality:tbl:1](#pandas:functionality:tbl:1) представлены аргументы\n",
+ "функции `reindex`."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Таблица 3 : Аргументы функции `reindex` \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Аргумент | Описание |
\n",
+ "\n",
+ "\n",
+ " index | Новая последовательность для использования в качестве индекса. Может быть экземпляром Index или любой последовательности Python |
\n",
+ " method | Метод интерполяции (заполнения): ffil (forward-fill) — прямое заполнение, bfill (backward-fill) — обратное заполнение |
\n",
+ " fill_value | Подставляется это значения при заполнении пропущенных данных, которые появляются при переиндексации |
\n",
+ " limit | При заполнении задает максимальный размер шага (по количеству элементов) заполнения |
\n",
+ " tolerance | При заполнении задает максимальный размер шага (в абсолютном числовом расстоянии) для заполнения неточных совпадений |
\n",
+ " level | Сопоставляет простой Index на уровне MultiIndex; в противном случае выбирает подмножество |
\n",
+ " copy | Если True, всегда копирует данные, даже если новый индекс эквивалентен старому; если False не копирует данные, если индексы эквивалентны |
\n",
+ "\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "## Удаление записей с оси\n",
+ "\n",
+ "\n",
+ "Удалить одну или несколько записей легко, если имеется массив или\n",
+ "список индексов, которые не содержат эти записи. Поскольку это может\n",
+ "потребовать некоторых операций над множествами, метод `drop`\n",
+ "возвращает новый объект с указанными значениями, удаленными с оси:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "new_obj = obj.drop('c')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.drop(['d', 'c'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В `DataFrame` значения индекса могут быть удалены с любой оси:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "data = pd.DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Вызов `drop` с последовательностью меток удаляет значения из меток\n",
+ "строк (ось `0`):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "data.drop(['Colorado', 'Ohio'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Удалить значения в столбцах можно передавая параметр `axis=1` или\n",
+ "`axis=columns`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "data.drop('two', axis=1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "data.drop(['two', 'four'], axis='columns')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Многие функции, такие как `drop`, которые изменяют размер или форму\n",
+ "`Series` или `DataFrame`, могут изменять сам объект (*in-place*) без\n",
+ "создания нового объекта:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.drop('c', inplace=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "> **Предупреждение.**\n",
+ ">\n",
+ "> Будьте осторожны с параметром `inplace`, так как происходит **удаление**\n",
+ "> данных.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Арифметические операции и выравнивание данных\n",
+ "\n",
+ "\n",
+ "Важной особенностью `pandas` для некоторых приложений является поведение\n",
+ "арифметических операций между объектами с разными индексами. При\n",
+ "сложении объекты в случае, когда любые пары индексов отличаются,\n",
+ "соответствующий индекс в результате является объединением исходных\n",
+ "индексов:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1], index=['a', 'c', 'e', 'f', 'g'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "s1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "s2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "s1 + s2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Выравнивание данных вводит пропущенные значения в местах\n",
+ "меток, которые не пересекаются. Пропущенные значения будут\n",
+ "распространяться в дальнейших арифметических вычислениях.\n",
+ "\n",
+ "В случае `DataFrame` выравнивание осуществляется как для строк, так и\n",
+ "для столбцов:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'), \n",
+ " \t index=['Ohio', 'Texas', 'Colorado'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), \n",
+ " \t index=['Utah', 'Ohio', 'Texas', 'Oregon'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Сумма введенных объектов вернет новый объект `DataFrame`, чьи индексы\n",
+ "и столбцы являются объединениями индексов и столбцов двух складываемых\n",
+ "объектов:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1 + df2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Так как столбцы `'c'` и `'e'` не находятся одновременно в обоих\n",
+ "объектах `DataFrame`, в результате они содержат отсутствующие\n",
+ "значения. Такое же происходит и со строками.\n",
+ "\n",
+ "Если сложить объекты `DataFrame` без общих меток столбцов или строк,\n",
+ "результат будет содержать все отсутствующие значения:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1 = pd.DataFrame({'A': [1, 2]})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df2 = pd.DataFrame({'B': [3, 4]})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1 - df2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Арифметические методы с заполнением значений\n",
+ "\n",
+ ""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)), columns=list('abcd'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)), columns=list('abcde'))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df2.loc[1, 'b'] = np.nan"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Сложение этих объектов приводит к значениям NA в местах, которые не\n",
+ "перекрываются:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1 + df2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Для заполнения отсутствующих значений можно воспользоваться функцией\n",
+ "`add` с дополнительным аргументом `fill_value`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1.add(df2, fill_value=0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В таблице [pandas:functionality:tbl:2](#pandas:functionality:tbl:2) представлены методы для\n",
+ "арифметических операций. У каждого из них есть аналог, начинающийся с\n",
+ "буквы `r`, у которого переставлены аргументы. Приведенные ниже\n",
+ "примеры эквивалентны:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "1 / df1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1.rdiv(1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Соответственно, при переиндексации `Series` или `DataFrame` вы также\n",
+ "можете указать другое значение заполнения:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df1.reindex(columns=df2.columns, fill_value=0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Таблица 4 : Гибкие арифметические методы \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Метод | Описание |
\n",
+ "\n",
+ "\n",
+ " add, radd | Сложение (+) |
\n",
+ " sub, rsub | Вычитание (-) |
\n",
+ " div, rdiv | Деление (/) |
\n",
+ " floordiv, rfloordiv | Целочисленное деление (//) |
\n",
+ " mul, rmul | Умножение (*) |
\n",
+ " pow, rpow | Возведение в степень (**) |
\n",
+ "\n",
+ "
\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Операции между объектами `DataFrame` и `Series`\n",
+ "\n",
+ "\n",
+ "Как и для массивов NumPy разной размерности, существуют арифметические\n",
+ "операции между объектами `DataFrame` и `Series`. В качестве примера\n",
+ "рассмотрим разность между двумерным массивом и одной из его строк:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "arr = np.arange(12.).reshape((3, 4))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "arr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "arr[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "arr - arr[0]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "При вычитании `arr[0]` из `arr`, операция осуществляется для каждой\n",
+ "строки. Операции между `DataFrame` и `Series` производятся аналогично."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame = pd.DataFrame(np.arange(12.).reshape((4, 3)), \n",
+ " columns=list('bde'), \n",
+ " index=['Utah', 'Ohio', 'Texas', 'Oregon'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "series = frame.iloc[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "series"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "По умолчанию арифметические операции между `DataFrame` и `Series`\n",
+ "приводят индексы объекта `Series` к столбцам объекта `DataFrame`,\n",
+ "распространяя операцию по строкам:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame - series"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Если значение индекса не найдено ни в столбцах `DataFrame`, ни в индексе\n",
+ "`Series`, объекты будут переиндексированы для формирования\n",
+ "объединения:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "series2 = pd.Series(range(3), index=['b', 'e', 'f'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame + series2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Если вместо согласования по столбцам нужно согласовывать операцию по\n",
+ "строкам, нужно использовать арифметический метод:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "series3 = frame['d']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "series3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.sub(series3, axis='index')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Применение функций и отображение\n",
+ "\n",
+ "\n",
+ "Универсальные функции NumPy также работают с объектами `pandas`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "np.abs(frame)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Другой частой операцией является применение функции к одномерным\n",
+ "массивам для каждого столбца или строки. Метод `apply` объекта\n",
+ "`DataFrame` выполняет это:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "f = lambda x: x.max() - x.min()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.apply(f)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В результате мы получили объект `Series`, у которого индекс совпадает\n",
+ "со столбцами объекта `DataFrame`.\n",
+ "\n",
+ "Если задать параметр `axis = 'columns'` в функции `apply`, функция\n",
+ "будет применяться к строкам:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.apply(f, axis='columns')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Многие из наиболее распространенных статистических методов\n",
+ "(например, `sum` и `mean`) являются методами `DataFrame`, поэтому \n",
+ "использование `apply` не обязательно. \n",
+ "\n",
+ "Функция, передаваемая в `apply`, не обязана возвращать скалярное\n",
+ "значение, она может также возвращать объект `Series`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def f(x): \n",
+ " return pd.Series([x.min(), x.max()], index=['min', 'max'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.apply(f)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Также можно использовать поэлементные функции. Предположим, нужно\n",
+ "получить форматированную строку для каждого значения в объекте\n",
+ "`frame`. Это можно реализовать с помощью функции `applymap`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "format = lambda x: '%.2f' % x"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.applymap(format)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В функции `applymap` используется метод `map` класса `Series`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame['e'].map(format)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Сортировка и ранжирование\n",
+ "\n",
+ "\n",
+ "Одна из важных встроенных операций — это сортировка данных. Для того,\n",
+ "чтобы выполнить лексикографическую сортировку по индексам строк или\n",
+ "столбцов, можно использовать функцию `sort_index`, которая возвращает\n",
+ "новый отсортированный объект:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.sort_index()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Объект `DataFrame` можно сортировать по индексам на любой оси:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame = pd.DataFrame(np.arange(8).reshape((2, 4)), index=['three', 'one'], columns=['d', 'a', 'b', 'c'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.sort_index()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.sort_index(axis=1)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Данные сортируются по возрастанию по умолчанию, но могут быть\n",
+ "отсортированы также по убыванию:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.sort_index(axis=1, ascending=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Для сортировки объекта `Series` по значениям используется метод\n",
+ "`sort_values`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series([4, 7, -3, 2])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.sort_values()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Все пропущенные значения по умолчанию сортируются в конец объекта\n",
+ "`Series`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series([4, np.nan, 7, np.nan, -3, 2])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.sort_values()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "При сортировке объекта `DataFrame` можно использовать данные в одном\n",
+ "или нескольких столбцах в качестве ключей для сортировки. Чтобы\n",
+ "выполнить это, необходимо передать имя одного или нескольких столбцов\n",
+ "параметру `by` метода `sort_vlues`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.sort_values(by='b')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Для сортировки по нескольким столбцам, необходимо передать список\n",
+ "имен столбцов:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.sort_values(by=['a', 'b'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "*Ранжирование* заключается в присвоении *ранга* от единицы до числа значений в \n",
+ "массиве. Объекты `Series` и `DataFrame` имеют метод `rank`, который по\n",
+ "умолчанию разрывает связи, присваивая каждой группе среднее значение\n",
+ "ранга:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series([7, -5, 7, 4, 2, 0, 4])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.rank()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Ранги также могут быть назначены в соответствии с порядком, в котором\n",
+ "они наблюдаются в данных:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.rank(method='first')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Здесь вместо использования среднего ранга $6.5$ для записей с\n",
+ "индексами `0` и `2` они вместо этого были установлены на $6$ и $7$,\n",
+ "потому что метка $0$ предшествует метке $2$ в данных.\n",
+ "\n",
+ "В таблице [pandas:functionality:tbl:3](#pandas:functionality:tbl:3) представлен перечень методов\n",
+ "построения ранга.\n",
+ "\n",
+ "Объект `DataFrame` может вычислять ранги по строкам или по столбцам:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1], 'c': [-2, 5, 8, -2.5]})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "frame.rank(axis='columns')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Таблица 5 : Методы ранжирования \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Метод | Описание |
\n",
+ "\n",
+ "\n",
+ " average | Используется по умолчанию. Присваивает среднее значение ранга каждому значению в группе |
\n",
+ " min | Использует минимальный ранг для всей группы |
\n",
+ " max | Использует максимальный ранг для всей группы |
\n",
+ " first | Присваивает ранги в порядке появления значений в данных |
\n",
+ " dense | Как method = 'min', но ранги между группами всегда увеличиваются на 1, а не на количество равных элементов в группе |
\n",
+ "\n",
+ "
\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "## Индексация с повторяющимися метками\n",
+ "\n",
+ "\n",
+ "В рассматриваемых выше примерах индексы имели единственные значения,\n",
+ "без повторений. Хотя многие функции библиотеки `pandas` (например,\n",
+ "`reindex`) требуют, чтобы метки были уникальными, это не\n",
+ "обязательно. Рассмотрим ряд с повторяющимися индексами:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "У объекта `Index` есть атрибут `is_unique`, который дает информацию\n",
+ "являются ли метки индекса уникальными:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.index.is_unique"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В случае, когда несколько данных имеют одинаковые метки, обращение по\n",
+ "этому индексу вернет объект `Series`, в то время как для меток без\n",
+ "дублирования возвращается скалярное значение:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj['a']"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj['c']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Та же логика распространяется и на индексирование строк в `DataFrame`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'b'])"
+ ]
+ },
+ {
+ "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.loc['b']"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Описательная и сводная статистика\n",
+ "\n",
+ "\n",
+ "Объекты\t`pandas` оснащены набором общих математических и\n",
+ "статистических методов. Большинство из них попадают в категорию\n",
+ "сводной статистики. В отличие от соответствующих методов массивов\n",
+ "NumPy методы объектов `pandas` имеют встроенную обработку пропущенных\n",
+ "значений. Рассмотрим небольшой объект `DataFrame`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame([[1.4, np.nan], [7.1, -4.5], [np.nan, np.nan], [0.75, -1.3]], index=['a', 'b', 'c', 'd'], columns=['one', 'two'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Вызов метода `sum` возвращает суммы значений по столбцам:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df.sum()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Чтобы получить суммы значений по строкам нужно передать параметр\n",
+ "`axis='columns'` или `axis=1`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df.sum(axis='columns')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Значения NA исключаются, если только весь срез (в данном случае строка\n",
+ "или столбец) не равен NA. Это поведение можно изменить с помощью\n",
+ "параметра `skipna`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df.mean(axis='columns', skipna=False)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Некоторые методы, такие как `idxmin` и `idxmax`, возвращают косвенную \n",
+ "статистику, такую как значение индекса, где достигаются минимальные\n",
+ "или максимальные значения:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df.idxmax()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Есть методы являются аккумулирующими:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df.cumsum()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Метод `describe` возвращает множественную суммарную статистику:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df.describe()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "На нечисловых данных метод `describe` возвращает следующую информацию:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj = pd.Series(['a', 'a', 'b', 'c'] * 4)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "obj.describe()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "В таблице [pandas:statistics:tbl:1](#pandas:statistics:tbl:1) представлен полный список\n",
+ "методов сводной статистики и связанных с этим методов:\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "## Таблица 6 : Описательная и сводная статистика \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Метод | Описание |
\n",
+ "\n",
+ "\n",
+ " count | Количество нечисловых значений |
\n",
+ " describe | Вычисляет сводную статистику для ряда или для каждого столбца объекта DataFrame |
\n",
+ " min, max | Вычисляет минимальное и максимальное значение |
\n",
+ " argmin, argmax | Возвращают индекс (целое число), где расположено минимальное или максимальное значение |
\n",
+ " idxmin, idxmax | Возвращают метку индекса, где расположено минимальное или максимальное значение |
\n",
+ " quantile | Вычисляет квантиль выборки от 0 до 1 |
\n",
+ " sum | Сумма значений |
\n",
+ " mean | Среднее значение |
\n",
+ " median | Медиана (50-процентная квантиль) значений |
\n",
+ " mad | Среднее абсолютное отклонение от среднего значения |
\n",
+ " prod | Произведение значений |
\n",
+ " var | Дисперсия множества выборки значений |
\n",
+ " std | Стандартное отклонение выборки значений |
\n",
+ " skew | Асимметрия (третий момент) выборки значений |
\n",
+ " kurt | Эксцесс (четвертый момент) выборки значений |
\n",
+ " cumsum | Накопленная сумма значений |
\n",
+ " cummin, cummax | Совокупный минимум и максимум |
\n",
+ " cumprod | Накопленное произведение значений |
\n",
+ " diff | Вычисляет первую арифметическую разность (полезно для временных рядов) |
\n",
+ " pct_change | Вычисляет процентные изменения |
\n",
+ "\n",
+ "
\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Чтение и запись данных\n",
+ "\n",
+ "\n",
+ "В библиотеке `pandas` реализованы функции чтения табличных данных в\n",
+ "объект `DataFrame`. В таблице [pandas:rwdata:tbl:1](#pandas:rwdata:tbl:1) представлены\n",
+ "некоторые из таких функций.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Таблица 7 : Функции чтения данных \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Функция | Описание |
\n",
+ "\n",
+ "\n",
+ " read_csv | Загружает разделенные значения из файла или файлоподобного объекта; в качестве разделителя по умолчанию используется запятая |
\n",
+ " read_table | Загружает разделенные значения из файла или файлоподобного объекта; в качестве разделителя по умолчанию используется табуляция ('\\t') |
\n",
+ " read_fwf | Читает данные в формате со столбцами фиксированной длины (без разделителей) |
\n",
+ " read_clipboard | Версия функции read_table, которая читает данные из буфера обмена |
\n",
+ " read_excel | Читает данные из файлов формата .xls или .xlsx |
\n",
+ " read_hdf | Читает файлы вормата HDF5, записанные с помощью библиотеки pandas |
\n",
+ " read_html | Читает все таблицы из заданного документа HTML |
\n",
+ " read_json | Читает данные из JSON (JavsScript Object Notation) |
\n",
+ " read_msgpack | Читает данные pandas закодированные с помощью двоичного формата MessagePack |
\n",
+ " read_pickle | Читает любой объект, сохраненный в формате Python pickle |
\n",
+ " read_sas | Читает набор данных SAS, хранящийся в одном из пользовательских форматов хранения системы SAS |
\n",
+ " read_sql | Читает результат запроса SQL (используя SQLAlchemy) как объект DataFrame |
\n",
+ "\n",
+ "
\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Библиотека `pandas` поддерживает нативную работу со многими\n",
+ "реляционными БД.\n",
+ "\n",
+ "Можно не только загружать данные из локальных файлов, но и из\n",
+ "Интернета — достаточно вместо адреса на локальном компьютере указать\n",
+ "прямю ссылку на файл.\n",
+ "\n",
+ "Также существует дополнительный пакет, который называется\n",
+ "`pandas_datareader`. Если он не установлен, его можно установить через\n",
+ "`conda` или `pip`. Он загружает данные из некоторых\n",
+ "источников. Загрузим с помощью `pandas_datareader` некоторые данные\n",
+ "для некоторых биржевых тикеров:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import pandas_datareader.data as web\n",
+ "\n",
+ "all_data = {ticker: web.get_data_yahoo(ticker)\n",
+ " for ticker in ['AAPL', 'IBM', 'MSFT', 'GOOG']}\n",
+ "price = pd.DataFrame({ticker: data['Adj Close']\n",
+ " for ticker, data in all_data.items()})\n",
+ "volume = pd.DataFrame({ticker: data['Volume']\n",
+ " for ticker, data in all_data.items()})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Вычислим изменение процентные изменения цен:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "returns = price.pct_change()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "returns.tail()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Метод `corr` объекта `Series` вычисляет корреляцию перекрывающихся,\n",
+ "выровненных по индексу значений в двух объектах\n",
+ "`Series`. Соответственно `cov` вычисляет ковариацию:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "returns['MSFT'].corr(returns['IBM'])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "returns['MSFT'].cov(returns['IBM'])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Поскольку `MSFT` является допустимым атрибутом Python, мы также можем\n",
+ "выбрать эти столбцы, используя более краткий синтаксис"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "returns.MSFT.corr(returns.IBM)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Методы `corr` и `cov` объекта `DataFrame` возвращают полные матрицы\n",
+ "корреляции или ковариации:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "returns.corr()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "returns.cov()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Используя метод `corrwith` объекта `DataFrame`, можно вычислять попарные\n",
+ "корреляции между столбцами или строками `DataFrame` с другими\n",
+ "объектами `Series` или `DataFrame`. Передача в качестве аргумента ряда\n",
+ "возвращает ряд со значением корреляции, вычисленным для каждого\n",
+ "столбца:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": false,
+ "jupyter": {
+ "outputs_hidden": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "returns.corrwith(returns.IBM)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "# Задания\n",
+ "\n",
+ "\n",
+ "\n",
+ "Предлагается поработать с\n",
+ "[набором данных](https://data.lacity.org/A-Safe-City/Crime-Data-from-2010-to-2019/63jg-8b9z)\n",
+ "о преступности в Лос-Анджелесе.\n",
+ "\n",
+ "Результат работы должен быть в виде блокнота Jupyter. Все задачи в\n",
+ "одном блокноте, например, `pandas-da-ans.ipynb`.\n",
+ "\n",
+ "Для построения графических данных смотрите главу [Графическая \n",
+ "визуализация данных](visual.ipynb)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "## Быстрый анализ данных\n",
+ "\n",
+ "\n",
+ "* Загрузите [случайную выборку](src-pandas/la-crimes-sample.csv.zip) из этого набора.\n",
+ "\n",
+ "* Сколько строк и столбцов в таблице?\n",
+ "\n",
+ "* Каковы названия столбцов?\n",
+ "\n",
+ "* Какие типы данных у столбцов?\n",
+ "\n",
+ "* Сколько в каждом из них уникальных значений?\n",
+ "\n",
+ "* Сколько пропущенных значений?\n",
+ "\n",
+ "* Постройте распределения числовых переменных?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Жертвы\n",
+ "\n",
+ "\n",
+ "В наборе данных имеется информация о Возрасте, Поле, и Происхождении\n",
+ "каждой жертвы. Есть ли связь между этими признаками? \n",
+ "\n",
+ "* Верно ли, что женщины чаще оказываются жертвами по сравнению с мужчинами?\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "## Преступления, пол и возраст\n",
+ "\n",
+ "\n",
+ "* Изучите распределение количества преступлений по возрасту. Какова тенденция? Люди какого возраста чаще всего подвергаются преступлениям? Есть ли локальные минимумы? Используйте типы графиков `hist` и `density`. \n",
+ "\n",
+ "* Как различается вероятность женщин и мужчин стать жертвой в зависимости от возраста? Постройте визуализацию. В каком возрастном промежутке мужчины чаще становятся жетрвами преступлений?\n",
+ "\n",
+ "* Определите 10 самых распространенных преступлений в Лос-Анджелесе. Постройте график.\n",
+ "\n",
+ "* От каких преступлений чаще старадют женщины, а от каких мужчины?\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Происхождение\n",
+ "\n",
+ "\n",
+ "\n",
+ "## Таблица 8\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Символ | Происхождение |
\n",
+ "\n",
+ "\n",
+ " 'A' | Other Asian |
\n",
+ " 'B' | Black |
\n",
+ " 'C' | Chinese |
\n",
+ " 'D' | Cambodian |
\n",
+ " 'F' | Filipino |
\n",
+ " 'G' | Guamanian |
\n",
+ " 'H' | Hispanic/Latin/Mexican |
\n",
+ " 'I' | American Indian/Alaskan Native |
\n",
+ " 'J' | Japanesea |
\n",
+ " 'K' | Korean |
\n",
+ " 'L' | Laotian |
\n",
+ " 'O' | Other |
\n",
+ " 'P' | Pacific Islander |
\n",
+ " 'S' | Samoan |
\n",
+ " 'U' | Hawaiian |
\n",
+ " 'V' | Vietnamese |
\n",
+ " 'W' | White |
\n",
+ " 'X' | Unknown |
\n",
+ " 'Z' | Asian Indian |
\n",
+ "\n",
+ "
\n",
+ "\n",
+ "\n",
+ "* Люди какого происхождения чаще всего подвергаются преступлениям?\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Место проишествия\n",
+ "\n",
+ "\n",
+ "* Отсортируйте районы, по количеству преступлений. Постройте график, показывающий самые безопасный и опасный районы.\n",
+ "\n",
+ "* Люди какого происхождения чаще всего страдают от преступлений в каждом из районов? Не забудьте нормировать на общее количество жертв.\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ ""
+ ]
+ }
+ ],
+ "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"
+ },
+ "toc-autonumbering": false,
+ "toc-showcode": false,
+ "toc-showmarkdowntxt": false,
+ "toc-showtags": false
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/src-pandas/datareader.py b/src-pandas/datareader.py
new file mode 100644
index 0000000..c82495f
--- /dev/null
+++ b/src-pandas/datareader.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+import pandas as pd
+import pandas_datareader.data as web
+
+all_data = {ticker: web.get_data_yahoo(ticker)
+ for ticker in ['AAPL', 'IBM', 'MSFT', 'GOOG']}
+price = pd.DataFrame({ticker: data['Adj Close']
+ for ticker, data in all_data.items()})
+volume = pd.DataFrame({ticker: data['Volume']
+ for ticker, data in all_data.items()})
+
+#End 1st block
diff --git a/src-pandas/la-crimes-sample.csv.zip b/src-pandas/la-crimes-sample.csv.zip
new file mode 100644
index 0000000..b0a7e3b
Binary files /dev/null and b/src-pandas/la-crimes-sample.csv.zip differ
diff --git a/src-visual/macrodata.csv b/src-visual/macrodata.csv
new file mode 100644
index 0000000..2496f7c
--- /dev/null
+++ b/src-visual/macrodata.csv
@@ -0,0 +1,204 @@
+year,quarter,realgdp,realcons,realinv,realgovt,realdpi,cpi,m1,tbilrate,unemp,pop,infl,realint
+1959.0,1.0,2710.349,1707.4,286.898,470.045,1886.9,28.98,139.7,2.82,5.8,177.146,0.0,0.0
+1959.0,2.0,2778.801,1733.7,310.859,481.301,1919.7,29.15,141.7,3.08,5.1,177.83,2.34,0.74
+1959.0,3.0,2775.488,1751.8,289.226,491.26,1916.4,29.35,140.5,3.82,5.3,178.657,2.74,1.09
+1959.0,4.0,2785.204,1753.7,299.356,484.052,1931.3,29.37,140.0,4.33,5.6,179.386,0.27,4.06
+1960.0,1.0,2847.699,1770.5,331.722,462.199,1955.5,29.54,139.6,3.5,5.2,180.007,2.31,1.19
+1960.0,2.0,2834.39,1792.9,298.152,460.4,1966.1,29.55,140.2,2.68,5.2,180.671,0.14,2.55
+1960.0,3.0,2839.022,1785.8,296.375,474.676,1967.8,29.75,140.9,2.36,5.6,181.528,2.7,-0.34
+1960.0,4.0,2802.616,1788.2,259.764,476.434,1966.6,29.84,141.1,2.29,6.3,182.287,1.21,1.08
+1961.0,1.0,2819.264,1787.7,266.405,475.854,1984.5,29.81,142.1,2.37,6.8,182.992,-0.4,2.77
+1961.0,2.0,2872.005,1814.3,286.246,480.328,2014.4,29.92,142.9,2.29,7.0,183.691,1.47,0.81
+1961.0,3.0,2918.419,1823.1,310.227,493.828,2041.9,29.98,144.1,2.32,6.8,184.524,0.8,1.52
+1961.0,4.0,2977.83,1859.6,315.463,502.521,2082.0,30.04,145.2,2.6,6.2,185.242,0.8,1.8
+1962.0,1.0,3031.241,1879.4,334.271,520.96,2101.7,30.21,146.4,2.73,5.6,185.874,2.26,0.47
+1962.0,2.0,3064.709,1902.5,331.039,523.066,2125.2,30.22,146.5,2.78,5.5,186.538,0.13,2.65
+1962.0,3.0,3093.047,1917.9,336.962,538.838,2137.0,30.38,146.7,2.78,5.6,187.323,2.11,0.67
+1962.0,4.0,3100.563,1945.1,325.65,535.912,2154.6,30.44,148.3,2.87,5.5,188.013,0.79,2.08
+1963.0,1.0,3141.087,1958.2,343.721,522.917,2172.5,30.48,149.7,2.9,5.8,188.58,0.53,2.38
+1963.0,2.0,3180.447,1976.9,348.73,518.108,2193.1,30.69,151.3,3.03,5.7,189.242,2.75,0.29
+1963.0,3.0,3240.332,2003.8,360.102,546.893,2217.9,30.75,152.6,3.38,5.5,190.028,0.78,2.6
+1963.0,4.0,3264.967,2020.6,364.534,532.383,2254.6,30.94,153.7,3.52,5.6,190.668,2.46,1.06
+1964.0,1.0,3338.246,2060.5,379.523,529.686,2299.6,30.95,154.8,3.51,5.5,191.245,0.13,3.38
+1964.0,2.0,3376.587,2096.7,377.778,526.175,2362.1,31.02,156.8,3.47,5.2,191.889,0.9,2.57
+1964.0,3.0,3422.469,2135.2,386.754,522.008,2392.7,31.12,159.2,3.53,5.0,192.631,1.29,2.25
+1964.0,4.0,3431.957,2141.2,389.91,514.603,2420.4,31.28,160.7,3.76,5.0,193.223,2.05,1.71
+1965.0,1.0,3516.251,2188.8,429.145,508.006,2447.4,31.38,162.0,3.93,4.9,193.709,1.28,2.65
+1965.0,2.0,3563.96,2213.0,429.119,508.931,2474.5,31.58,163.1,3.84,4.7,194.303,2.54,1.3
+1965.0,3.0,3636.285,2251.0,444.444,529.446,2542.6,31.65,166.0,3.93,4.4,194.997,0.89,3.04
+1965.0,4.0,3724.014,2314.3,446.493,544.121,2594.1,31.88,169.1,4.35,4.1,195.539,2.9,1.46
+1966.0,1.0,3815.423,2348.5,484.244,556.593,2618.4,32.28,171.8,4.62,3.9,195.999,4.99,-0.37
+1966.0,2.0,3828.124,2354.5,475.408,571.371,2624.7,32.45,170.3,4.65,3.8,196.56,2.1,2.55
+1966.0,3.0,3853.301,2381.5,470.697,594.514,2657.8,32.85,171.2,5.23,3.8,197.207,4.9,0.33
+1966.0,4.0,3884.52,2391.4,472.957,599.528,2688.2,32.9,171.9,5.0,3.7,197.736,0.61,4.39
+1967.0,1.0,3918.74,2405.3,460.007,640.682,2728.4,33.1,174.2,4.22,3.8,198.206,2.42,1.8
+1967.0,2.0,3919.556,2438.1,440.393,631.43,2750.8,33.4,178.1,3.78,3.8,198.712,3.61,0.17
+1967.0,3.0,3950.826,2450.6,453.033,641.504,2777.1,33.7,181.6,4.42,3.8,199.311,3.58,0.84
+1967.0,4.0,3980.97,2465.7,462.834,640.234,2797.4,34.1,184.3,4.9,3.9,199.808,4.72,0.18
+1968.0,1.0,4063.013,2524.6,472.907,651.378,2846.2,34.4,186.6,5.18,3.7,200.208,3.5,1.67
+1968.0,2.0,4131.998,2563.3,492.026,646.145,2893.5,34.9,190.5,5.5,3.5,200.706,5.77,-0.28
+1968.0,3.0,4160.267,2611.5,476.053,640.615,2899.3,35.3,194.0,5.21,3.5,201.29,4.56,0.65
+1968.0,4.0,4178.293,2623.5,480.998,636.729,2918.4,35.7,198.7,5.85,3.4,201.76,4.51,1.34
+1969.0,1.0,4244.1,2652.9,512.686,633.224,2923.4,36.3,200.7,6.08,3.4,202.161,6.67,-0.58
+1969.0,2.0,4256.46,2669.8,508.601,623.16,2952.9,36.8,201.7,6.49,3.4,202.677,5.47,1.02
+1969.0,3.0,4283.378,2682.7,520.36,623.613,3012.9,37.3,202.9,7.02,3.6,203.302,5.4,1.63
+1969.0,4.0,4263.261,2704.1,492.334,606.9,3034.9,37.9,206.2,7.64,3.6,203.849,6.38,1.26
+1970.0,1.0,4256.573,2720.7,476.925,594.888,3050.1,38.5,206.7,6.76,4.2,204.401,6.28,0.47
+1970.0,2.0,4264.289,2733.2,478.419,576.257,3103.5,38.9,208.0,6.66,4.8,205.052,4.13,2.52
+1970.0,3.0,4302.259,2757.1,486.594,567.743,3145.4,39.4,212.9,6.15,5.2,205.788,5.11,1.04
+1970.0,4.0,4256.637,2749.6,458.406,564.666,3135.1,39.9,215.5,4.86,5.8,206.466,5.04,-0.18
+1971.0,1.0,4374.016,2802.2,517.935,542.709,3197.3,40.1,220.0,3.65,5.9,207.065,2.0,1.65
+1971.0,2.0,4398.829,2827.9,533.986,534.905,3245.3,40.6,224.9,4.76,5.9,207.661,4.96,-0.19
+1971.0,3.0,4433.943,2850.4,541.01,532.646,3259.7,40.9,227.2,4.7,6.0,208.345,2.94,1.75
+1971.0,4.0,4446.264,2897.8,524.085,516.14,3294.2,41.2,230.1,3.87,6.0,208.917,2.92,0.95
+1972.0,1.0,4525.769,2936.5,561.147,518.192,3314.9,41.5,235.6,3.55,5.8,209.386,2.9,0.64
+1972.0,2.0,4633.101,2992.6,595.495,526.473,3346.1,41.8,238.8,3.86,5.7,209.896,2.88,0.98
+1972.0,3.0,4677.503,3038.8,603.97,498.116,3414.6,42.2,245.0,4.47,5.6,210.479,3.81,0.66
+1972.0,4.0,4754.546,3110.1,607.104,496.54,3550.5,42.7,251.5,5.09,5.3,210.985,4.71,0.38
+1973.0,1.0,4876.166,3167.0,645.654,504.838,3590.7,43.7,252.7,5.98,5.0,211.42,9.26,-3.28
+1973.0,2.0,4932.571,3165.4,675.837,497.033,3626.2,44.2,257.5,7.19,4.9,211.909,4.55,2.64
+1973.0,3.0,4906.252,3176.7,649.412,475.897,3644.4,45.6,259.0,8.06,4.8,212.475,12.47,-4.41
+1973.0,4.0,4953.05,3167.4,674.253,476.174,3688.9,46.8,263.8,7.68,4.8,212.932,10.39,-2.71
+1974.0,1.0,4909.617,3139.7,631.23,491.043,3632.3,48.1,267.2,7.8,5.1,213.361,10.96,-3.16
+1974.0,2.0,4922.188,3150.6,628.102,490.177,3601.1,49.3,269.3,7.89,5.2,213.854,9.86,-1.96
+1974.0,3.0,4873.52,3163.6,592.672,492.586,3612.4,51.0,272.3,8.16,5.6,214.451,13.56,-5.4
+1974.0,4.0,4854.34,3117.3,598.306,496.176,3596.0,52.3,273.9,6.96,6.6,214.931,10.07,-3.11
+1975.0,1.0,4795.295,3143.4,493.212,490.603,3581.9,53.0,276.2,5.53,8.2,215.353,5.32,0.22
+1975.0,2.0,4831.942,3195.8,476.085,486.679,3749.3,54.0,283.7,5.57,8.9,215.973,7.48,-1.91
+1975.0,3.0,4913.328,3241.4,516.402,498.836,3698.6,54.9,285.4,6.27,8.5,216.587,6.61,-0.34
+1975.0,4.0,4977.511,3275.7,530.596,500.141,3736.0,55.8,288.4,5.26,8.3,217.095,6.5,-1.24
+1976.0,1.0,5090.663,3341.2,585.541,495.568,3791.0,56.1,294.7,4.91,7.7,217.528,2.14,2.77
+1976.0,2.0,5128.947,3371.8,610.513,494.532,3822.2,57.0,297.2,5.28,7.6,218.035,6.37,-1.09
+1976.0,3.0,5154.072,3407.5,611.646,493.141,3856.7,57.9,302.0,5.05,7.7,218.644,6.27,-1.22
+1976.0,4.0,5191.499,3451.8,615.898,494.415,3884.4,58.7,308.3,4.57,7.8,219.179,5.49,-0.92
+1977.0,1.0,5251.762,3491.3,646.198,498.509,3887.5,60.0,316.0,4.6,7.5,219.684,8.76,-4.16
+1977.0,2.0,5356.131,3510.6,696.141,506.695,3931.8,60.8,320.2,5.06,7.1,220.239,5.3,-0.24
+1977.0,3.0,5451.921,3544.1,734.078,509.605,3990.8,61.6,326.4,5.82,6.9,220.904,5.23,0.59
+1977.0,4.0,5450.793,3597.5,713.356,504.584,4071.2,62.7,334.4,6.2,6.6,221.477,7.08,-0.88
+1978.0,1.0,5469.405,3618.5,727.504,506.314,4096.4,63.9,339.9,6.34,6.3,221.991,7.58,-1.24
+1978.0,2.0,5684.569,3695.9,777.454,518.366,4143.4,65.5,347.6,6.72,6.0,222.585,9.89,-3.18
+1978.0,3.0,5740.3,3711.4,801.452,520.199,4177.1,67.1,353.3,7.64,6.0,223.271,9.65,-2.01
+1978.0,4.0,5816.222,3741.3,819.689,524.782,4209.8,68.5,358.6,9.02,5.9,223.865,8.26,0.76
+1979.0,1.0,5825.949,3760.2,819.556,525.524,4255.9,70.6,368.0,9.42,5.9,224.438,12.08,-2.66
+1979.0,2.0,5831.418,3758.0,817.66,532.04,4226.1,73.0,377.2,9.3,5.7,225.055,13.37,-4.07
+1979.0,3.0,5873.335,3794.9,801.742,531.232,4250.3,75.2,380.8,10.49,5.9,225.801,11.88,-1.38
+1979.0,4.0,5889.495,3805.0,786.817,531.126,4284.3,78.0,385.8,11.94,5.9,226.451,14.62,-2.68
+1980.0,1.0,5908.467,3798.4,781.114,548.115,4296.2,80.9,383.8,13.75,6.3,227.061,14.6,-0.85
+1980.0,2.0,5787.373,3712.2,710.64,561.895,4236.1,82.6,394.0,7.9,7.3,227.726,8.32,-0.42
+1980.0,3.0,5776.617,3752.0,656.477,554.292,4279.7,84.7,409.0,10.34,7.7,228.417,10.04,0.3
+1980.0,4.0,5883.46,3802.0,723.22,556.13,4368.1,87.2,411.3,14.75,7.4,228.937,11.64,3.11
+1981.0,1.0,6005.717,3822.8,795.091,567.618,4358.1,89.1,427.4,13.95,7.4,229.403,8.62,5.32
+1981.0,2.0,5957.795,3822.8,757.24,584.54,4358.6,91.5,426.9,15.33,7.4,229.966,10.63,4.69
+1981.0,3.0,6030.184,3838.3,804.242,583.89,4455.4,93.4,428.4,14.58,7.4,230.641,8.22,6.36
+1981.0,4.0,5955.062,3809.3,773.053,590.125,4464.4,94.4,442.7,11.33,8.2,231.157,4.26,7.07
+1982.0,1.0,5857.333,3833.9,692.514,591.043,4469.6,95.0,447.1,12.95,8.8,231.645,2.53,10.42
+1982.0,2.0,5889.074,3847.7,691.9,596.403,4500.8,97.5,448.0,11.97,9.4,232.188,10.39,1.58
+1982.0,3.0,5866.37,3877.2,683.825,605.37,4520.6,98.1,464.5,8.1,9.9,232.816,2.45,5.65
+1982.0,4.0,5871.001,3947.9,622.93,623.307,4536.4,97.9,477.2,7.96,10.7,233.322,-0.82,8.77
+1983.0,1.0,5944.02,3986.6,645.11,630.873,4572.2,98.8,493.2,8.22,10.4,233.781,3.66,4.56
+1983.0,2.0,6077.619,4065.7,707.372,644.322,4605.5,99.8,507.8,8.69,10.1,234.307,4.03,4.66
+1983.0,3.0,6197.468,4137.6,754.937,662.412,4674.7,100.8,517.2,8.99,9.4,234.907,3.99,5.01
+1983.0,4.0,6325.574,4203.2,834.427,639.197,4771.1,102.1,525.1,8.89,8.5,235.385,5.13,3.76
+1984.0,1.0,6448.264,4239.2,921.763,644.635,4875.4,103.3,535.0,9.43,7.9,235.839,4.67,4.76
+1984.0,2.0,6559.594,4299.9,952.841,664.839,4959.4,104.1,540.9,9.94,7.5,236.348,3.09,6.85
+1984.0,3.0,6623.343,4333.0,974.989,662.294,5036.6,105.1,543.7,10.19,7.4,236.976,3.82,6.37
+1984.0,4.0,6677.264,4390.1,958.993,684.282,5084.5,105.7,557.0,8.14,7.3,237.468,2.28,5.87
+1985.0,1.0,6740.275,4464.6,927.375,691.613,5072.0,107.0,570.4,8.25,7.3,237.9,4.89,3.36
+1985.0,2.0,6797.344,4505.2,943.383,708.524,5172.7,107.7,589.1,7.17,7.3,238.466,2.61,4.56
+1985.0,3.0,6903.523,4590.8,932.959,732.305,5140.7,108.5,607.8,7.13,7.2,239.113,2.96,4.17
+1985.0,4.0,6955.918,4600.9,969.434,732.026,5193.9,109.9,621.4,7.14,7.0,239.638,5.13,2.01
+1986.0,1.0,7022.757,4639.3,967.442,728.125,5255.8,108.7,641.0,6.56,7.0,240.094,-4.39,10.95
+1986.0,2.0,7050.969,4688.7,945.972,751.334,5315.5,109.5,670.3,6.06,7.2,240.651,2.93,3.13
+1986.0,3.0,7118.95,4770.7,916.315,779.77,5343.3,110.2,694.9,5.31,7.0,241.274,2.55,2.76
+1986.0,4.0,7153.359,4799.4,917.736,767.671,5346.5,111.4,730.2,5.44,6.8,241.784,4.33,1.1
+1987.0,1.0,7193.019,4792.1,945.776,772.247,5379.4,112.7,743.9,5.61,6.6,242.252,4.64,0.97
+1987.0,2.0,7269.51,4856.3,947.1,782.962,5321.0,113.8,743.0,5.67,6.3,242.804,3.89,1.79
+1987.0,3.0,7332.558,4910.4,948.055,783.804,5416.2,115.0,756.2,6.19,6.0,243.446,4.2,1.99
+1987.0,4.0,7458.022,4922.2,1021.98,795.467,5493.1,116.0,756.2,5.76,5.9,243.981,3.46,2.29
+1988.0,1.0,7496.6,5004.4,964.398,773.851,5562.1,117.2,768.1,5.76,5.7,244.445,4.12,1.64
+1988.0,2.0,7592.881,5040.8,987.858,765.98,5614.3,118.5,781.4,6.48,5.5,245.021,4.41,2.07
+1988.0,3.0,7632.082,5080.6,994.204,760.245,5657.5,119.9,783.3,7.22,5.5,245.693,4.7,2.52
+1988.0,4.0,7733.991,5140.4,1007.371,783.065,5708.5,121.2,785.7,8.03,5.3,246.224,4.31,3.72
+1989.0,1.0,7806.603,5159.3,1045.975,767.024,5773.4,123.1,779.2,8.67,5.2,246.721,6.22,2.44
+1989.0,2.0,7865.016,5182.4,1033.753,784.275,5749.8,124.5,777.8,8.15,5.2,247.342,4.52,3.63
+1989.0,3.0,7927.393,5236.1,1021.604,791.819,5787.0,125.4,786.6,7.76,5.3,248.067,2.88,4.88
+1989.0,4.0,7944.697,5261.7,1011.119,787.844,5831.3,127.5,795.4,7.65,5.4,248.659,6.64,1.01
+1990.0,1.0,8027.693,5303.3,1021.07,799.681,5875.1,128.9,806.2,7.8,5.3,249.306,4.37,3.44
+1990.0,2.0,8059.598,5320.8,1021.36,800.639,5913.9,130.5,810.1,7.7,5.3,250.132,4.93,2.76
+1990.0,3.0,8059.476,5341.0,997.319,793.513,5918.1,133.4,819.8,7.33,5.7,251.057,8.79,-1.46
+1990.0,4.0,7988.864,5299.5,934.248,800.525,5878.2,134.7,827.2,6.67,6.1,251.889,3.88,2.79
+1991.0,1.0,7950.164,5284.4,896.21,806.775,5896.3,135.1,843.2,5.83,6.6,252.643,1.19,4.65
+1991.0,2.0,8003.822,5324.7,891.704,809.081,5941.1,136.2,861.5,5.54,6.8,253.493,3.24,2.29
+1991.0,3.0,8037.538,5345.0,913.904,793.987,5953.6,137.2,878.0,5.18,6.9,254.435,2.93,2.25
+1991.0,4.0,8069.046,5342.6,948.891,778.378,5992.4,138.3,910.4,4.14,7.1,255.214,3.19,0.95
+1992.0,1.0,8157.616,5434.5,927.796,778.568,6082.9,139.4,943.8,3.88,7.4,255.992,3.17,0.71
+1992.0,2.0,8244.294,5466.7,988.912,777.762,6129.5,140.5,963.2,3.5,7.6,256.894,3.14,0.36
+1992.0,3.0,8329.361,5527.1,999.135,786.639,6160.6,141.7,1003.8,2.97,7.6,257.861,3.4,-0.44
+1992.0,4.0,8417.016,5594.6,1030.758,787.064,6248.2,142.8,1030.4,3.12,7.4,258.679,3.09,0.02
+1993.0,1.0,8432.485,5617.2,1054.979,762.901,6156.5,143.8,1047.6,2.92,7.2,259.414,2.79,0.13
+1993.0,2.0,8486.435,5671.1,1063.263,752.158,6252.3,144.5,1084.5,3.02,7.1,260.255,1.94,1.08
+1993.0,3.0,8531.108,5732.7,1062.514,744.227,6265.7,145.6,1113.0,3.0,6.8,261.163,3.03,-0.04
+1993.0,4.0,8643.769,5783.7,1118.583,748.102,6358.1,146.3,1131.6,3.05,6.6,261.919,1.92,1.13
+1994.0,1.0,8727.919,5848.1,1166.845,721.288,6332.6,147.2,1141.1,3.48,6.6,262.631,2.45,1.02
+1994.0,2.0,8847.303,5891.5,1234.855,717.197,6440.6,148.4,1150.5,4.2,6.2,263.436,3.25,0.96
+1994.0,3.0,8904.289,5938.7,1212.655,736.89,6487.9,149.4,1150.1,4.68,6.0,264.301,2.69,2.0
+1994.0,4.0,9003.18,5997.3,1269.19,716.702,6574.0,150.5,1151.4,5.53,5.6,265.044,2.93,2.6
+1995.0,1.0,9025.267,6004.3,1282.09,715.326,6616.6,151.8,1149.3,5.72,5.5,265.755,3.44,2.28
+1995.0,2.0,9044.668,6053.5,1247.61,712.492,6617.2,152.6,1145.4,5.52,5.7,266.557,2.1,3.42
+1995.0,3.0,9120.684,6107.6,1235.601,707.649,6666.8,153.5,1137.3,5.32,5.7,267.456,2.35,2.97
+1995.0,4.0,9184.275,6150.6,1270.392,681.081,6706.2,154.7,1123.5,5.17,5.6,268.151,3.11,2.05
+1996.0,1.0,9247.188,6206.9,1287.128,695.265,6777.7,156.1,1124.8,4.91,5.5,268.853,3.6,1.31
+1996.0,2.0,9407.052,6277.1,1353.795,705.172,6850.6,157.0,1112.4,5.09,5.5,269.667,2.3,2.79
+1996.0,3.0,9488.879,6314.6,1422.059,692.741,6908.9,158.2,1086.1,5.04,5.3,270.581,3.05,2.0
+1996.0,4.0,9592.458,6366.1,1418.193,690.744,6946.8,159.4,1081.5,4.99,5.3,271.36,3.02,1.97
+1997.0,1.0,9666.235,6430.2,1451.304,681.445,7008.9,159.9,1063.8,5.1,5.2,272.083,1.25,3.85
+1997.0,2.0,9809.551,6456.2,1543.976,693.525,7061.5,160.4,1066.2,5.01,5.0,272.912,1.25,3.76
+1997.0,3.0,9932.672,6566.0,1571.426,691.261,7142.4,161.5,1065.5,5.02,4.9,273.852,2.73,2.29
+1997.0,4.0,10008.874,6641.1,1596.523,690.311,7241.5,162.0,1074.4,5.11,4.7,274.626,1.24,3.88
+1998.0,1.0,10103.425,6707.2,1672.732,668.783,7406.2,162.2,1076.1,5.02,4.6,275.304,0.49,4.53
+1998.0,2.0,10194.277,6822.6,1652.716,687.184,7512.0,163.2,1075.0,4.98,4.4,276.115,2.46,2.52
+1998.0,3.0,10328.787,6913.1,1700.071,681.472,7591.0,163.9,1086.0,4.49,4.5,277.003,1.71,2.78
+1998.0,4.0,10507.575,7019.1,1754.743,688.147,7646.5,164.7,1097.8,4.38,4.4,277.79,1.95,2.43
+1999.0,1.0,10601.179,7088.3,1809.993,683.601,7698.4,165.9,1101.9,4.39,4.3,278.451,2.9,1.49
+1999.0,2.0,10684.049,7199.9,1803.674,683.594,7716.0,166.7,1098.7,4.54,4.3,279.295,1.92,2.62
+1999.0,3.0,10819.914,7286.4,1848.949,697.936,7765.9,168.1,1102.3,4.75,4.2,280.203,3.35,1.41
+1999.0,4.0,11014.254,7389.2,1914.567,713.445,7887.7,169.3,1121.9,5.2,4.1,280.976,2.85,2.35
+2000.0,1.0,11043.044,7501.3,1887.836,685.216,8053.4,170.9,1113.5,5.63,4.0,281.653,3.76,1.87
+2000.0,2.0,11258.454,7571.8,2018.529,712.641,8135.9,172.7,1103.0,5.81,3.9,282.385,4.19,1.62
+2000.0,3.0,11267.867,7645.9,1986.956,698.827,8222.3,173.9,1098.7,6.07,4.0,283.19,2.77,3.3
+2000.0,4.0,11334.544,7713.5,1987.845,695.597,8234.6,175.6,1097.7,5.7,3.9,283.9,3.89,1.81
+2001.0,1.0,11297.171,7744.3,1882.691,710.403,8296.5,176.4,1114.9,4.39,4.2,284.55,1.82,2.57
+2001.0,2.0,11371.251,7773.5,1876.65,725.623,8273.7,177.4,1139.7,3.54,4.4,285.267,2.26,1.28
+2001.0,3.0,11340.075,7807.7,1837.074,730.493,8484.5,177.6,1166.0,2.72,4.8,286.047,0.45,2.27
+2001.0,4.0,11380.128,7930.0,1731.189,739.318,8385.5,177.7,1190.9,1.74,5.5,286.728,0.23,1.51
+2002.0,1.0,11477.868,7957.3,1789.327,756.915,8611.6,179.3,1185.9,1.75,5.7,287.328,3.59,-1.84
+2002.0,2.0,11538.77,7997.8,1810.779,774.408,8658.9,180.0,1199.5,1.7,5.8,288.028,1.56,0.14
+2002.0,3.0,11596.43,8052.0,1814.531,786.673,8629.2,181.2,1204.0,1.61,5.7,288.783,2.66,-1.05
+2002.0,4.0,11598.824,8080.6,1813.219,799.967,8649.6,182.6,1226.8,1.2,5.8,289.421,3.08,-1.88
+2003.0,1.0,11645.819,8122.3,1813.141,800.196,8681.3,183.2,1248.4,1.14,5.9,290.019,1.31,-0.17
+2003.0,2.0,11738.706,8197.8,1823.698,838.775,8812.5,183.7,1287.9,0.96,6.2,290.704,1.09,-0.13
+2003.0,3.0,11935.461,8312.1,1889.883,839.598,8935.4,184.9,1297.3,0.94,6.1,291.449,2.6,-1.67
+2003.0,4.0,12042.817,8358.0,1959.783,845.722,8986.4,186.3,1306.1,0.9,5.8,292.057,3.02,-2.11
+2004.0,1.0,12127.623,8437.6,1970.015,856.57,9025.9,187.4,1332.1,0.94,5.7,292.635,2.35,-1.42
+2004.0,2.0,12213.818,8483.2,2055.58,861.44,9115.0,189.1,1340.5,1.21,5.6,293.31,3.61,-2.41
+2004.0,3.0,12303.533,8555.8,2082.231,876.385,9175.9,190.8,1361.0,1.63,5.4,294.066,3.58,-1.95
+2004.0,4.0,12410.282,8654.2,2125.152,865.596,9303.4,191.8,1366.6,2.2,5.4,294.741,2.09,0.11
+2005.0,1.0,12534.113,8719.0,2170.299,869.204,9189.6,193.8,1357.8,2.69,5.3,295.308,4.15,-1.46
+2005.0,2.0,12587.535,8802.9,2131.468,870.044,9253.0,194.7,1366.6,3.01,5.1,295.994,1.85,1.16
+2005.0,3.0,12683.153,8865.6,2154.949,890.394,9308.0,199.2,1375.0,3.52,5.0,296.77,9.14,-5.62
+2005.0,4.0,12748.699,8888.5,2232.193,875.557,9358.7,199.4,1380.6,4.0,4.9,297.435,0.4,3.6
+2006.0,1.0,12915.938,8986.6,2264.721,900.511,9533.8,200.7,1380.5,4.51,4.7,298.061,2.6,1.91
+2006.0,2.0,12962.462,9035.0,2261.247,892.839,9617.3,202.7,1369.2,4.82,4.7,298.766,3.97,0.85
+2006.0,3.0,12965.916,9090.7,2229.636,892.002,9662.5,201.9,1369.4,4.9,4.7,299.593,-1.58,6.48
+2006.0,4.0,13060.679,9181.6,2165.966,894.404,9788.8,203.574,1373.6,4.92,4.4,300.32,3.3,1.62
+2007.0,1.0,13099.901,9265.1,2132.609,882.766,9830.2,205.92,1379.7,4.95,4.5,300.977,4.58,0.36
+2007.0,2.0,13203.977,9291.5,2162.214,898.713,9842.7,207.338,1370.0,4.72,4.5,301.714,2.75,1.97
+2007.0,3.0,13321.109,9335.6,2166.491,918.983,9883.9,209.133,1379.2,4.0,4.7,302.509,3.45,0.55
+2007.0,4.0,13391.249,9363.6,2123.426,925.11,9886.2,212.495,1377.4,3.01,4.8,303.204,6.38,-3.37
+2008.0,1.0,13366.865,9349.6,2082.886,943.372,9826.8,213.997,1384.0,1.56,4.9,303.803,2.82,-1.26
+2008.0,2.0,13415.266,9351.0,2026.518,961.28,10059.0,218.61,1409.3,1.74,5.4,304.483,8.53,-6.79
+2008.0,3.0,13324.6,9267.7,1990.693,991.551,9838.3,216.889,1474.7,1.17,6.0,305.27,-3.16,4.33
+2008.0,4.0,13141.92,9195.3,1857.661,1007.273,9920.4,212.174,1576.5,0.12,6.9,305.952,-8.79,8.91
+2009.0,1.0,12925.41,9209.2,1558.494,996.287,9926.4,212.671,1592.8,0.22,8.1,306.547,0.94,-0.71
+2009.0,2.0,12901.504,9189.0,1456.678,1023.528,10077.5,214.469,1653.6,0.18,9.2,307.226,3.37,-3.19
+2009.0,3.0,12990.341,9256.0,1486.398,1044.088,10040.6,216.385,1673.9,0.12,9.6,308.013,3.56,-3.44
diff --git a/src-visual/macrodata.csv.txt b/src-visual/macrodata.csv.txt
new file mode 100644
index 0000000..2496f7c
--- /dev/null
+++ b/src-visual/macrodata.csv.txt
@@ -0,0 +1,204 @@
+year,quarter,realgdp,realcons,realinv,realgovt,realdpi,cpi,m1,tbilrate,unemp,pop,infl,realint
+1959.0,1.0,2710.349,1707.4,286.898,470.045,1886.9,28.98,139.7,2.82,5.8,177.146,0.0,0.0
+1959.0,2.0,2778.801,1733.7,310.859,481.301,1919.7,29.15,141.7,3.08,5.1,177.83,2.34,0.74
+1959.0,3.0,2775.488,1751.8,289.226,491.26,1916.4,29.35,140.5,3.82,5.3,178.657,2.74,1.09
+1959.0,4.0,2785.204,1753.7,299.356,484.052,1931.3,29.37,140.0,4.33,5.6,179.386,0.27,4.06
+1960.0,1.0,2847.699,1770.5,331.722,462.199,1955.5,29.54,139.6,3.5,5.2,180.007,2.31,1.19
+1960.0,2.0,2834.39,1792.9,298.152,460.4,1966.1,29.55,140.2,2.68,5.2,180.671,0.14,2.55
+1960.0,3.0,2839.022,1785.8,296.375,474.676,1967.8,29.75,140.9,2.36,5.6,181.528,2.7,-0.34
+1960.0,4.0,2802.616,1788.2,259.764,476.434,1966.6,29.84,141.1,2.29,6.3,182.287,1.21,1.08
+1961.0,1.0,2819.264,1787.7,266.405,475.854,1984.5,29.81,142.1,2.37,6.8,182.992,-0.4,2.77
+1961.0,2.0,2872.005,1814.3,286.246,480.328,2014.4,29.92,142.9,2.29,7.0,183.691,1.47,0.81
+1961.0,3.0,2918.419,1823.1,310.227,493.828,2041.9,29.98,144.1,2.32,6.8,184.524,0.8,1.52
+1961.0,4.0,2977.83,1859.6,315.463,502.521,2082.0,30.04,145.2,2.6,6.2,185.242,0.8,1.8
+1962.0,1.0,3031.241,1879.4,334.271,520.96,2101.7,30.21,146.4,2.73,5.6,185.874,2.26,0.47
+1962.0,2.0,3064.709,1902.5,331.039,523.066,2125.2,30.22,146.5,2.78,5.5,186.538,0.13,2.65
+1962.0,3.0,3093.047,1917.9,336.962,538.838,2137.0,30.38,146.7,2.78,5.6,187.323,2.11,0.67
+1962.0,4.0,3100.563,1945.1,325.65,535.912,2154.6,30.44,148.3,2.87,5.5,188.013,0.79,2.08
+1963.0,1.0,3141.087,1958.2,343.721,522.917,2172.5,30.48,149.7,2.9,5.8,188.58,0.53,2.38
+1963.0,2.0,3180.447,1976.9,348.73,518.108,2193.1,30.69,151.3,3.03,5.7,189.242,2.75,0.29
+1963.0,3.0,3240.332,2003.8,360.102,546.893,2217.9,30.75,152.6,3.38,5.5,190.028,0.78,2.6
+1963.0,4.0,3264.967,2020.6,364.534,532.383,2254.6,30.94,153.7,3.52,5.6,190.668,2.46,1.06
+1964.0,1.0,3338.246,2060.5,379.523,529.686,2299.6,30.95,154.8,3.51,5.5,191.245,0.13,3.38
+1964.0,2.0,3376.587,2096.7,377.778,526.175,2362.1,31.02,156.8,3.47,5.2,191.889,0.9,2.57
+1964.0,3.0,3422.469,2135.2,386.754,522.008,2392.7,31.12,159.2,3.53,5.0,192.631,1.29,2.25
+1964.0,4.0,3431.957,2141.2,389.91,514.603,2420.4,31.28,160.7,3.76,5.0,193.223,2.05,1.71
+1965.0,1.0,3516.251,2188.8,429.145,508.006,2447.4,31.38,162.0,3.93,4.9,193.709,1.28,2.65
+1965.0,2.0,3563.96,2213.0,429.119,508.931,2474.5,31.58,163.1,3.84,4.7,194.303,2.54,1.3
+1965.0,3.0,3636.285,2251.0,444.444,529.446,2542.6,31.65,166.0,3.93,4.4,194.997,0.89,3.04
+1965.0,4.0,3724.014,2314.3,446.493,544.121,2594.1,31.88,169.1,4.35,4.1,195.539,2.9,1.46
+1966.0,1.0,3815.423,2348.5,484.244,556.593,2618.4,32.28,171.8,4.62,3.9,195.999,4.99,-0.37
+1966.0,2.0,3828.124,2354.5,475.408,571.371,2624.7,32.45,170.3,4.65,3.8,196.56,2.1,2.55
+1966.0,3.0,3853.301,2381.5,470.697,594.514,2657.8,32.85,171.2,5.23,3.8,197.207,4.9,0.33
+1966.0,4.0,3884.52,2391.4,472.957,599.528,2688.2,32.9,171.9,5.0,3.7,197.736,0.61,4.39
+1967.0,1.0,3918.74,2405.3,460.007,640.682,2728.4,33.1,174.2,4.22,3.8,198.206,2.42,1.8
+1967.0,2.0,3919.556,2438.1,440.393,631.43,2750.8,33.4,178.1,3.78,3.8,198.712,3.61,0.17
+1967.0,3.0,3950.826,2450.6,453.033,641.504,2777.1,33.7,181.6,4.42,3.8,199.311,3.58,0.84
+1967.0,4.0,3980.97,2465.7,462.834,640.234,2797.4,34.1,184.3,4.9,3.9,199.808,4.72,0.18
+1968.0,1.0,4063.013,2524.6,472.907,651.378,2846.2,34.4,186.6,5.18,3.7,200.208,3.5,1.67
+1968.0,2.0,4131.998,2563.3,492.026,646.145,2893.5,34.9,190.5,5.5,3.5,200.706,5.77,-0.28
+1968.0,3.0,4160.267,2611.5,476.053,640.615,2899.3,35.3,194.0,5.21,3.5,201.29,4.56,0.65
+1968.0,4.0,4178.293,2623.5,480.998,636.729,2918.4,35.7,198.7,5.85,3.4,201.76,4.51,1.34
+1969.0,1.0,4244.1,2652.9,512.686,633.224,2923.4,36.3,200.7,6.08,3.4,202.161,6.67,-0.58
+1969.0,2.0,4256.46,2669.8,508.601,623.16,2952.9,36.8,201.7,6.49,3.4,202.677,5.47,1.02
+1969.0,3.0,4283.378,2682.7,520.36,623.613,3012.9,37.3,202.9,7.02,3.6,203.302,5.4,1.63
+1969.0,4.0,4263.261,2704.1,492.334,606.9,3034.9,37.9,206.2,7.64,3.6,203.849,6.38,1.26
+1970.0,1.0,4256.573,2720.7,476.925,594.888,3050.1,38.5,206.7,6.76,4.2,204.401,6.28,0.47
+1970.0,2.0,4264.289,2733.2,478.419,576.257,3103.5,38.9,208.0,6.66,4.8,205.052,4.13,2.52
+1970.0,3.0,4302.259,2757.1,486.594,567.743,3145.4,39.4,212.9,6.15,5.2,205.788,5.11,1.04
+1970.0,4.0,4256.637,2749.6,458.406,564.666,3135.1,39.9,215.5,4.86,5.8,206.466,5.04,-0.18
+1971.0,1.0,4374.016,2802.2,517.935,542.709,3197.3,40.1,220.0,3.65,5.9,207.065,2.0,1.65
+1971.0,2.0,4398.829,2827.9,533.986,534.905,3245.3,40.6,224.9,4.76,5.9,207.661,4.96,-0.19
+1971.0,3.0,4433.943,2850.4,541.01,532.646,3259.7,40.9,227.2,4.7,6.0,208.345,2.94,1.75
+1971.0,4.0,4446.264,2897.8,524.085,516.14,3294.2,41.2,230.1,3.87,6.0,208.917,2.92,0.95
+1972.0,1.0,4525.769,2936.5,561.147,518.192,3314.9,41.5,235.6,3.55,5.8,209.386,2.9,0.64
+1972.0,2.0,4633.101,2992.6,595.495,526.473,3346.1,41.8,238.8,3.86,5.7,209.896,2.88,0.98
+1972.0,3.0,4677.503,3038.8,603.97,498.116,3414.6,42.2,245.0,4.47,5.6,210.479,3.81,0.66
+1972.0,4.0,4754.546,3110.1,607.104,496.54,3550.5,42.7,251.5,5.09,5.3,210.985,4.71,0.38
+1973.0,1.0,4876.166,3167.0,645.654,504.838,3590.7,43.7,252.7,5.98,5.0,211.42,9.26,-3.28
+1973.0,2.0,4932.571,3165.4,675.837,497.033,3626.2,44.2,257.5,7.19,4.9,211.909,4.55,2.64
+1973.0,3.0,4906.252,3176.7,649.412,475.897,3644.4,45.6,259.0,8.06,4.8,212.475,12.47,-4.41
+1973.0,4.0,4953.05,3167.4,674.253,476.174,3688.9,46.8,263.8,7.68,4.8,212.932,10.39,-2.71
+1974.0,1.0,4909.617,3139.7,631.23,491.043,3632.3,48.1,267.2,7.8,5.1,213.361,10.96,-3.16
+1974.0,2.0,4922.188,3150.6,628.102,490.177,3601.1,49.3,269.3,7.89,5.2,213.854,9.86,-1.96
+1974.0,3.0,4873.52,3163.6,592.672,492.586,3612.4,51.0,272.3,8.16,5.6,214.451,13.56,-5.4
+1974.0,4.0,4854.34,3117.3,598.306,496.176,3596.0,52.3,273.9,6.96,6.6,214.931,10.07,-3.11
+1975.0,1.0,4795.295,3143.4,493.212,490.603,3581.9,53.0,276.2,5.53,8.2,215.353,5.32,0.22
+1975.0,2.0,4831.942,3195.8,476.085,486.679,3749.3,54.0,283.7,5.57,8.9,215.973,7.48,-1.91
+1975.0,3.0,4913.328,3241.4,516.402,498.836,3698.6,54.9,285.4,6.27,8.5,216.587,6.61,-0.34
+1975.0,4.0,4977.511,3275.7,530.596,500.141,3736.0,55.8,288.4,5.26,8.3,217.095,6.5,-1.24
+1976.0,1.0,5090.663,3341.2,585.541,495.568,3791.0,56.1,294.7,4.91,7.7,217.528,2.14,2.77
+1976.0,2.0,5128.947,3371.8,610.513,494.532,3822.2,57.0,297.2,5.28,7.6,218.035,6.37,-1.09
+1976.0,3.0,5154.072,3407.5,611.646,493.141,3856.7,57.9,302.0,5.05,7.7,218.644,6.27,-1.22
+1976.0,4.0,5191.499,3451.8,615.898,494.415,3884.4,58.7,308.3,4.57,7.8,219.179,5.49,-0.92
+1977.0,1.0,5251.762,3491.3,646.198,498.509,3887.5,60.0,316.0,4.6,7.5,219.684,8.76,-4.16
+1977.0,2.0,5356.131,3510.6,696.141,506.695,3931.8,60.8,320.2,5.06,7.1,220.239,5.3,-0.24
+1977.0,3.0,5451.921,3544.1,734.078,509.605,3990.8,61.6,326.4,5.82,6.9,220.904,5.23,0.59
+1977.0,4.0,5450.793,3597.5,713.356,504.584,4071.2,62.7,334.4,6.2,6.6,221.477,7.08,-0.88
+1978.0,1.0,5469.405,3618.5,727.504,506.314,4096.4,63.9,339.9,6.34,6.3,221.991,7.58,-1.24
+1978.0,2.0,5684.569,3695.9,777.454,518.366,4143.4,65.5,347.6,6.72,6.0,222.585,9.89,-3.18
+1978.0,3.0,5740.3,3711.4,801.452,520.199,4177.1,67.1,353.3,7.64,6.0,223.271,9.65,-2.01
+1978.0,4.0,5816.222,3741.3,819.689,524.782,4209.8,68.5,358.6,9.02,5.9,223.865,8.26,0.76
+1979.0,1.0,5825.949,3760.2,819.556,525.524,4255.9,70.6,368.0,9.42,5.9,224.438,12.08,-2.66
+1979.0,2.0,5831.418,3758.0,817.66,532.04,4226.1,73.0,377.2,9.3,5.7,225.055,13.37,-4.07
+1979.0,3.0,5873.335,3794.9,801.742,531.232,4250.3,75.2,380.8,10.49,5.9,225.801,11.88,-1.38
+1979.0,4.0,5889.495,3805.0,786.817,531.126,4284.3,78.0,385.8,11.94,5.9,226.451,14.62,-2.68
+1980.0,1.0,5908.467,3798.4,781.114,548.115,4296.2,80.9,383.8,13.75,6.3,227.061,14.6,-0.85
+1980.0,2.0,5787.373,3712.2,710.64,561.895,4236.1,82.6,394.0,7.9,7.3,227.726,8.32,-0.42
+1980.0,3.0,5776.617,3752.0,656.477,554.292,4279.7,84.7,409.0,10.34,7.7,228.417,10.04,0.3
+1980.0,4.0,5883.46,3802.0,723.22,556.13,4368.1,87.2,411.3,14.75,7.4,228.937,11.64,3.11
+1981.0,1.0,6005.717,3822.8,795.091,567.618,4358.1,89.1,427.4,13.95,7.4,229.403,8.62,5.32
+1981.0,2.0,5957.795,3822.8,757.24,584.54,4358.6,91.5,426.9,15.33,7.4,229.966,10.63,4.69
+1981.0,3.0,6030.184,3838.3,804.242,583.89,4455.4,93.4,428.4,14.58,7.4,230.641,8.22,6.36
+1981.0,4.0,5955.062,3809.3,773.053,590.125,4464.4,94.4,442.7,11.33,8.2,231.157,4.26,7.07
+1982.0,1.0,5857.333,3833.9,692.514,591.043,4469.6,95.0,447.1,12.95,8.8,231.645,2.53,10.42
+1982.0,2.0,5889.074,3847.7,691.9,596.403,4500.8,97.5,448.0,11.97,9.4,232.188,10.39,1.58
+1982.0,3.0,5866.37,3877.2,683.825,605.37,4520.6,98.1,464.5,8.1,9.9,232.816,2.45,5.65
+1982.0,4.0,5871.001,3947.9,622.93,623.307,4536.4,97.9,477.2,7.96,10.7,233.322,-0.82,8.77
+1983.0,1.0,5944.02,3986.6,645.11,630.873,4572.2,98.8,493.2,8.22,10.4,233.781,3.66,4.56
+1983.0,2.0,6077.619,4065.7,707.372,644.322,4605.5,99.8,507.8,8.69,10.1,234.307,4.03,4.66
+1983.0,3.0,6197.468,4137.6,754.937,662.412,4674.7,100.8,517.2,8.99,9.4,234.907,3.99,5.01
+1983.0,4.0,6325.574,4203.2,834.427,639.197,4771.1,102.1,525.1,8.89,8.5,235.385,5.13,3.76
+1984.0,1.0,6448.264,4239.2,921.763,644.635,4875.4,103.3,535.0,9.43,7.9,235.839,4.67,4.76
+1984.0,2.0,6559.594,4299.9,952.841,664.839,4959.4,104.1,540.9,9.94,7.5,236.348,3.09,6.85
+1984.0,3.0,6623.343,4333.0,974.989,662.294,5036.6,105.1,543.7,10.19,7.4,236.976,3.82,6.37
+1984.0,4.0,6677.264,4390.1,958.993,684.282,5084.5,105.7,557.0,8.14,7.3,237.468,2.28,5.87
+1985.0,1.0,6740.275,4464.6,927.375,691.613,5072.0,107.0,570.4,8.25,7.3,237.9,4.89,3.36
+1985.0,2.0,6797.344,4505.2,943.383,708.524,5172.7,107.7,589.1,7.17,7.3,238.466,2.61,4.56
+1985.0,3.0,6903.523,4590.8,932.959,732.305,5140.7,108.5,607.8,7.13,7.2,239.113,2.96,4.17
+1985.0,4.0,6955.918,4600.9,969.434,732.026,5193.9,109.9,621.4,7.14,7.0,239.638,5.13,2.01
+1986.0,1.0,7022.757,4639.3,967.442,728.125,5255.8,108.7,641.0,6.56,7.0,240.094,-4.39,10.95
+1986.0,2.0,7050.969,4688.7,945.972,751.334,5315.5,109.5,670.3,6.06,7.2,240.651,2.93,3.13
+1986.0,3.0,7118.95,4770.7,916.315,779.77,5343.3,110.2,694.9,5.31,7.0,241.274,2.55,2.76
+1986.0,4.0,7153.359,4799.4,917.736,767.671,5346.5,111.4,730.2,5.44,6.8,241.784,4.33,1.1
+1987.0,1.0,7193.019,4792.1,945.776,772.247,5379.4,112.7,743.9,5.61,6.6,242.252,4.64,0.97
+1987.0,2.0,7269.51,4856.3,947.1,782.962,5321.0,113.8,743.0,5.67,6.3,242.804,3.89,1.79
+1987.0,3.0,7332.558,4910.4,948.055,783.804,5416.2,115.0,756.2,6.19,6.0,243.446,4.2,1.99
+1987.0,4.0,7458.022,4922.2,1021.98,795.467,5493.1,116.0,756.2,5.76,5.9,243.981,3.46,2.29
+1988.0,1.0,7496.6,5004.4,964.398,773.851,5562.1,117.2,768.1,5.76,5.7,244.445,4.12,1.64
+1988.0,2.0,7592.881,5040.8,987.858,765.98,5614.3,118.5,781.4,6.48,5.5,245.021,4.41,2.07
+1988.0,3.0,7632.082,5080.6,994.204,760.245,5657.5,119.9,783.3,7.22,5.5,245.693,4.7,2.52
+1988.0,4.0,7733.991,5140.4,1007.371,783.065,5708.5,121.2,785.7,8.03,5.3,246.224,4.31,3.72
+1989.0,1.0,7806.603,5159.3,1045.975,767.024,5773.4,123.1,779.2,8.67,5.2,246.721,6.22,2.44
+1989.0,2.0,7865.016,5182.4,1033.753,784.275,5749.8,124.5,777.8,8.15,5.2,247.342,4.52,3.63
+1989.0,3.0,7927.393,5236.1,1021.604,791.819,5787.0,125.4,786.6,7.76,5.3,248.067,2.88,4.88
+1989.0,4.0,7944.697,5261.7,1011.119,787.844,5831.3,127.5,795.4,7.65,5.4,248.659,6.64,1.01
+1990.0,1.0,8027.693,5303.3,1021.07,799.681,5875.1,128.9,806.2,7.8,5.3,249.306,4.37,3.44
+1990.0,2.0,8059.598,5320.8,1021.36,800.639,5913.9,130.5,810.1,7.7,5.3,250.132,4.93,2.76
+1990.0,3.0,8059.476,5341.0,997.319,793.513,5918.1,133.4,819.8,7.33,5.7,251.057,8.79,-1.46
+1990.0,4.0,7988.864,5299.5,934.248,800.525,5878.2,134.7,827.2,6.67,6.1,251.889,3.88,2.79
+1991.0,1.0,7950.164,5284.4,896.21,806.775,5896.3,135.1,843.2,5.83,6.6,252.643,1.19,4.65
+1991.0,2.0,8003.822,5324.7,891.704,809.081,5941.1,136.2,861.5,5.54,6.8,253.493,3.24,2.29
+1991.0,3.0,8037.538,5345.0,913.904,793.987,5953.6,137.2,878.0,5.18,6.9,254.435,2.93,2.25
+1991.0,4.0,8069.046,5342.6,948.891,778.378,5992.4,138.3,910.4,4.14,7.1,255.214,3.19,0.95
+1992.0,1.0,8157.616,5434.5,927.796,778.568,6082.9,139.4,943.8,3.88,7.4,255.992,3.17,0.71
+1992.0,2.0,8244.294,5466.7,988.912,777.762,6129.5,140.5,963.2,3.5,7.6,256.894,3.14,0.36
+1992.0,3.0,8329.361,5527.1,999.135,786.639,6160.6,141.7,1003.8,2.97,7.6,257.861,3.4,-0.44
+1992.0,4.0,8417.016,5594.6,1030.758,787.064,6248.2,142.8,1030.4,3.12,7.4,258.679,3.09,0.02
+1993.0,1.0,8432.485,5617.2,1054.979,762.901,6156.5,143.8,1047.6,2.92,7.2,259.414,2.79,0.13
+1993.0,2.0,8486.435,5671.1,1063.263,752.158,6252.3,144.5,1084.5,3.02,7.1,260.255,1.94,1.08
+1993.0,3.0,8531.108,5732.7,1062.514,744.227,6265.7,145.6,1113.0,3.0,6.8,261.163,3.03,-0.04
+1993.0,4.0,8643.769,5783.7,1118.583,748.102,6358.1,146.3,1131.6,3.05,6.6,261.919,1.92,1.13
+1994.0,1.0,8727.919,5848.1,1166.845,721.288,6332.6,147.2,1141.1,3.48,6.6,262.631,2.45,1.02
+1994.0,2.0,8847.303,5891.5,1234.855,717.197,6440.6,148.4,1150.5,4.2,6.2,263.436,3.25,0.96
+1994.0,3.0,8904.289,5938.7,1212.655,736.89,6487.9,149.4,1150.1,4.68,6.0,264.301,2.69,2.0
+1994.0,4.0,9003.18,5997.3,1269.19,716.702,6574.0,150.5,1151.4,5.53,5.6,265.044,2.93,2.6
+1995.0,1.0,9025.267,6004.3,1282.09,715.326,6616.6,151.8,1149.3,5.72,5.5,265.755,3.44,2.28
+1995.0,2.0,9044.668,6053.5,1247.61,712.492,6617.2,152.6,1145.4,5.52,5.7,266.557,2.1,3.42
+1995.0,3.0,9120.684,6107.6,1235.601,707.649,6666.8,153.5,1137.3,5.32,5.7,267.456,2.35,2.97
+1995.0,4.0,9184.275,6150.6,1270.392,681.081,6706.2,154.7,1123.5,5.17,5.6,268.151,3.11,2.05
+1996.0,1.0,9247.188,6206.9,1287.128,695.265,6777.7,156.1,1124.8,4.91,5.5,268.853,3.6,1.31
+1996.0,2.0,9407.052,6277.1,1353.795,705.172,6850.6,157.0,1112.4,5.09,5.5,269.667,2.3,2.79
+1996.0,3.0,9488.879,6314.6,1422.059,692.741,6908.9,158.2,1086.1,5.04,5.3,270.581,3.05,2.0
+1996.0,4.0,9592.458,6366.1,1418.193,690.744,6946.8,159.4,1081.5,4.99,5.3,271.36,3.02,1.97
+1997.0,1.0,9666.235,6430.2,1451.304,681.445,7008.9,159.9,1063.8,5.1,5.2,272.083,1.25,3.85
+1997.0,2.0,9809.551,6456.2,1543.976,693.525,7061.5,160.4,1066.2,5.01,5.0,272.912,1.25,3.76
+1997.0,3.0,9932.672,6566.0,1571.426,691.261,7142.4,161.5,1065.5,5.02,4.9,273.852,2.73,2.29
+1997.0,4.0,10008.874,6641.1,1596.523,690.311,7241.5,162.0,1074.4,5.11,4.7,274.626,1.24,3.88
+1998.0,1.0,10103.425,6707.2,1672.732,668.783,7406.2,162.2,1076.1,5.02,4.6,275.304,0.49,4.53
+1998.0,2.0,10194.277,6822.6,1652.716,687.184,7512.0,163.2,1075.0,4.98,4.4,276.115,2.46,2.52
+1998.0,3.0,10328.787,6913.1,1700.071,681.472,7591.0,163.9,1086.0,4.49,4.5,277.003,1.71,2.78
+1998.0,4.0,10507.575,7019.1,1754.743,688.147,7646.5,164.7,1097.8,4.38,4.4,277.79,1.95,2.43
+1999.0,1.0,10601.179,7088.3,1809.993,683.601,7698.4,165.9,1101.9,4.39,4.3,278.451,2.9,1.49
+1999.0,2.0,10684.049,7199.9,1803.674,683.594,7716.0,166.7,1098.7,4.54,4.3,279.295,1.92,2.62
+1999.0,3.0,10819.914,7286.4,1848.949,697.936,7765.9,168.1,1102.3,4.75,4.2,280.203,3.35,1.41
+1999.0,4.0,11014.254,7389.2,1914.567,713.445,7887.7,169.3,1121.9,5.2,4.1,280.976,2.85,2.35
+2000.0,1.0,11043.044,7501.3,1887.836,685.216,8053.4,170.9,1113.5,5.63,4.0,281.653,3.76,1.87
+2000.0,2.0,11258.454,7571.8,2018.529,712.641,8135.9,172.7,1103.0,5.81,3.9,282.385,4.19,1.62
+2000.0,3.0,11267.867,7645.9,1986.956,698.827,8222.3,173.9,1098.7,6.07,4.0,283.19,2.77,3.3
+2000.0,4.0,11334.544,7713.5,1987.845,695.597,8234.6,175.6,1097.7,5.7,3.9,283.9,3.89,1.81
+2001.0,1.0,11297.171,7744.3,1882.691,710.403,8296.5,176.4,1114.9,4.39,4.2,284.55,1.82,2.57
+2001.0,2.0,11371.251,7773.5,1876.65,725.623,8273.7,177.4,1139.7,3.54,4.4,285.267,2.26,1.28
+2001.0,3.0,11340.075,7807.7,1837.074,730.493,8484.5,177.6,1166.0,2.72,4.8,286.047,0.45,2.27
+2001.0,4.0,11380.128,7930.0,1731.189,739.318,8385.5,177.7,1190.9,1.74,5.5,286.728,0.23,1.51
+2002.0,1.0,11477.868,7957.3,1789.327,756.915,8611.6,179.3,1185.9,1.75,5.7,287.328,3.59,-1.84
+2002.0,2.0,11538.77,7997.8,1810.779,774.408,8658.9,180.0,1199.5,1.7,5.8,288.028,1.56,0.14
+2002.0,3.0,11596.43,8052.0,1814.531,786.673,8629.2,181.2,1204.0,1.61,5.7,288.783,2.66,-1.05
+2002.0,4.0,11598.824,8080.6,1813.219,799.967,8649.6,182.6,1226.8,1.2,5.8,289.421,3.08,-1.88
+2003.0,1.0,11645.819,8122.3,1813.141,800.196,8681.3,183.2,1248.4,1.14,5.9,290.019,1.31,-0.17
+2003.0,2.0,11738.706,8197.8,1823.698,838.775,8812.5,183.7,1287.9,0.96,6.2,290.704,1.09,-0.13
+2003.0,3.0,11935.461,8312.1,1889.883,839.598,8935.4,184.9,1297.3,0.94,6.1,291.449,2.6,-1.67
+2003.0,4.0,12042.817,8358.0,1959.783,845.722,8986.4,186.3,1306.1,0.9,5.8,292.057,3.02,-2.11
+2004.0,1.0,12127.623,8437.6,1970.015,856.57,9025.9,187.4,1332.1,0.94,5.7,292.635,2.35,-1.42
+2004.0,2.0,12213.818,8483.2,2055.58,861.44,9115.0,189.1,1340.5,1.21,5.6,293.31,3.61,-2.41
+2004.0,3.0,12303.533,8555.8,2082.231,876.385,9175.9,190.8,1361.0,1.63,5.4,294.066,3.58,-1.95
+2004.0,4.0,12410.282,8654.2,2125.152,865.596,9303.4,191.8,1366.6,2.2,5.4,294.741,2.09,0.11
+2005.0,1.0,12534.113,8719.0,2170.299,869.204,9189.6,193.8,1357.8,2.69,5.3,295.308,4.15,-1.46
+2005.0,2.0,12587.535,8802.9,2131.468,870.044,9253.0,194.7,1366.6,3.01,5.1,295.994,1.85,1.16
+2005.0,3.0,12683.153,8865.6,2154.949,890.394,9308.0,199.2,1375.0,3.52,5.0,296.77,9.14,-5.62
+2005.0,4.0,12748.699,8888.5,2232.193,875.557,9358.7,199.4,1380.6,4.0,4.9,297.435,0.4,3.6
+2006.0,1.0,12915.938,8986.6,2264.721,900.511,9533.8,200.7,1380.5,4.51,4.7,298.061,2.6,1.91
+2006.0,2.0,12962.462,9035.0,2261.247,892.839,9617.3,202.7,1369.2,4.82,4.7,298.766,3.97,0.85
+2006.0,3.0,12965.916,9090.7,2229.636,892.002,9662.5,201.9,1369.4,4.9,4.7,299.593,-1.58,6.48
+2006.0,4.0,13060.679,9181.6,2165.966,894.404,9788.8,203.574,1373.6,4.92,4.4,300.32,3.3,1.62
+2007.0,1.0,13099.901,9265.1,2132.609,882.766,9830.2,205.92,1379.7,4.95,4.5,300.977,4.58,0.36
+2007.0,2.0,13203.977,9291.5,2162.214,898.713,9842.7,207.338,1370.0,4.72,4.5,301.714,2.75,1.97
+2007.0,3.0,13321.109,9335.6,2166.491,918.983,9883.9,209.133,1379.2,4.0,4.7,302.509,3.45,0.55
+2007.0,4.0,13391.249,9363.6,2123.426,925.11,9886.2,212.495,1377.4,3.01,4.8,303.204,6.38,-3.37
+2008.0,1.0,13366.865,9349.6,2082.886,943.372,9826.8,213.997,1384.0,1.56,4.9,303.803,2.82,-1.26
+2008.0,2.0,13415.266,9351.0,2026.518,961.28,10059.0,218.61,1409.3,1.74,5.4,304.483,8.53,-6.79
+2008.0,3.0,13324.6,9267.7,1990.693,991.551,9838.3,216.889,1474.7,1.17,6.0,305.27,-3.16,4.33
+2008.0,4.0,13141.92,9195.3,1857.661,1007.273,9920.4,212.174,1576.5,0.12,6.9,305.952,-8.79,8.91
+2009.0,1.0,12925.41,9209.2,1558.494,996.287,9926.4,212.671,1592.8,0.22,8.1,306.547,0.94,-0.71
+2009.0,2.0,12901.504,9189.0,1456.678,1023.528,10077.5,214.469,1653.6,0.18,9.2,307.226,3.37,-3.19
+2009.0,3.0,12990.341,9256.0,1486.398,1044.088,10040.6,216.385,1673.9,0.12,9.6,308.013,3.56,-3.44
diff --git a/src-visual/tips.csv b/src-visual/tips.csv
new file mode 100644
index 0000000..ee9be5f
--- /dev/null
+++ b/src-visual/tips.csv
@@ -0,0 +1,245 @@
+total_bill,tip,smoker,day,time,size
+16.99,1.01,No,Sun,Dinner,2
+10.34,1.66,No,Sun,Dinner,3
+21.01,3.5,No,Sun,Dinner,3
+23.68,3.31,No,Sun,Dinner,2
+24.59,3.61,No,Sun,Dinner,4
+25.29,4.71,No,Sun,Dinner,4
+8.77,2.0,No,Sun,Dinner,2
+26.88,3.12,No,Sun,Dinner,4
+15.04,1.96,No,Sun,Dinner,2
+14.78,3.23,No,Sun,Dinner,2
+10.27,1.71,No,Sun,Dinner,2
+35.26,5.0,No,Sun,Dinner,4
+15.42,1.57,No,Sun,Dinner,2
+18.43,3.0,No,Sun,Dinner,4
+14.83,3.02,No,Sun,Dinner,2
+21.58,3.92,No,Sun,Dinner,2
+10.33,1.67,No,Sun,Dinner,3
+16.29,3.71,No,Sun,Dinner,3
+16.97,3.5,No,Sun,Dinner,3
+20.65,3.35,No,Sat,Dinner,3
+17.92,4.08,No,Sat,Dinner,2
+20.29,2.75,No,Sat,Dinner,2
+15.77,2.23,No,Sat,Dinner,2
+39.42,7.58,No,Sat,Dinner,4
+19.82,3.18,No,Sat,Dinner,2
+17.81,2.34,No,Sat,Dinner,4
+13.37,2.0,No,Sat,Dinner,2
+12.69,2.0,No,Sat,Dinner,2
+21.7,4.3,No,Sat,Dinner,2
+19.65,3.0,No,Sat,Dinner,2
+9.55,1.45,No,Sat,Dinner,2
+18.35,2.5,No,Sat,Dinner,4
+15.06,3.0,No,Sat,Dinner,2
+20.69,2.45,No,Sat,Dinner,4
+17.78,3.27,No,Sat,Dinner,2
+24.06,3.6,No,Sat,Dinner,3
+16.31,2.0,No,Sat,Dinner,3
+16.93,3.07,No,Sat,Dinner,3
+18.69,2.31,No,Sat,Dinner,3
+31.27,5.0,No,Sat,Dinner,3
+16.04,2.24,No,Sat,Dinner,3
+17.46,2.54,No,Sun,Dinner,2
+13.94,3.06,No,Sun,Dinner,2
+9.68,1.32,No,Sun,Dinner,2
+30.4,5.6,No,Sun,Dinner,4
+18.29,3.0,No,Sun,Dinner,2
+22.23,5.0,No,Sun,Dinner,2
+32.4,6.0,No,Sun,Dinner,4
+28.55,2.05,No,Sun,Dinner,3
+18.04,3.0,No,Sun,Dinner,2
+12.54,2.5,No,Sun,Dinner,2
+10.29,2.6,No,Sun,Dinner,2
+34.81,5.2,No,Sun,Dinner,4
+9.94,1.56,No,Sun,Dinner,2
+25.56,4.34,No,Sun,Dinner,4
+19.49,3.51,No,Sun,Dinner,2
+38.01,3.0,Yes,Sat,Dinner,4
+26.41,1.5,No,Sat,Dinner,2
+11.24,1.76,Yes,Sat,Dinner,2
+48.27,6.73,No,Sat,Dinner,4
+20.29,3.21,Yes,Sat,Dinner,2
+13.81,2.0,Yes,Sat,Dinner,2
+11.02,1.98,Yes,Sat,Dinner,2
+18.29,3.76,Yes,Sat,Dinner,4
+17.59,2.64,No,Sat,Dinner,3
+20.08,3.15,No,Sat,Dinner,3
+16.45,2.47,No,Sat,Dinner,2
+3.07,1.0,Yes,Sat,Dinner,1
+20.23,2.01,No,Sat,Dinner,2
+15.01,2.09,Yes,Sat,Dinner,2
+12.02,1.97,No,Sat,Dinner,2
+17.07,3.0,No,Sat,Dinner,3
+26.86,3.14,Yes,Sat,Dinner,2
+25.28,5.0,Yes,Sat,Dinner,2
+14.73,2.2,No,Sat,Dinner,2
+10.51,1.25,No,Sat,Dinner,2
+17.92,3.08,Yes,Sat,Dinner,2
+27.2,4.0,No,Thur,Lunch,4
+22.76,3.0,No,Thur,Lunch,2
+17.29,2.71,No,Thur,Lunch,2
+19.44,3.0,Yes,Thur,Lunch,2
+16.66,3.4,No,Thur,Lunch,2
+10.07,1.83,No,Thur,Lunch,1
+32.68,5.0,Yes,Thur,Lunch,2
+15.98,2.03,No,Thur,Lunch,2
+34.83,5.17,No,Thur,Lunch,4
+13.03,2.0,No,Thur,Lunch,2
+18.28,4.0,No,Thur,Lunch,2
+24.71,5.85,No,Thur,Lunch,2
+21.16,3.0,No,Thur,Lunch,2
+28.97,3.0,Yes,Fri,Dinner,2
+22.49,3.5,No,Fri,Dinner,2
+5.75,1.0,Yes,Fri,Dinner,2
+16.32,4.3,Yes,Fri,Dinner,2
+22.75,3.25,No,Fri,Dinner,2
+40.17,4.73,Yes,Fri,Dinner,4
+27.28,4.0,Yes,Fri,Dinner,2
+12.03,1.5,Yes,Fri,Dinner,2
+21.01,3.0,Yes,Fri,Dinner,2
+12.46,1.5,No,Fri,Dinner,2
+11.35,2.5,Yes,Fri,Dinner,2
+15.38,3.0,Yes,Fri,Dinner,2
+44.3,2.5,Yes,Sat,Dinner,3
+22.42,3.48,Yes,Sat,Dinner,2
+20.92,4.08,No,Sat,Dinner,2
+15.36,1.64,Yes,Sat,Dinner,2
+20.49,4.06,Yes,Sat,Dinner,2
+25.21,4.29,Yes,Sat,Dinner,2
+18.24,3.76,No,Sat,Dinner,2
+14.31,4.0,Yes,Sat,Dinner,2
+14.0,3.0,No,Sat,Dinner,2
+7.25,1.0,No,Sat,Dinner,1
+38.07,4.0,No,Sun,Dinner,3
+23.95,2.55,No,Sun,Dinner,2
+25.71,4.0,No,Sun,Dinner,3
+17.31,3.5,No,Sun,Dinner,2
+29.93,5.07,No,Sun,Dinner,4
+10.65,1.5,No,Thur,Lunch,2
+12.43,1.8,No,Thur,Lunch,2
+24.08,2.92,No,Thur,Lunch,4
+11.69,2.31,No,Thur,Lunch,2
+13.42,1.68,No,Thur,Lunch,2
+14.26,2.5,No,Thur,Lunch,2
+15.95,2.0,No,Thur,Lunch,2
+12.48,2.52,No,Thur,Lunch,2
+29.8,4.2,No,Thur,Lunch,6
+8.52,1.48,No,Thur,Lunch,2
+14.52,2.0,No,Thur,Lunch,2
+11.38,2.0,No,Thur,Lunch,2
+22.82,2.18,No,Thur,Lunch,3
+19.08,1.5,No,Thur,Lunch,2
+20.27,2.83,No,Thur,Lunch,2
+11.17,1.5,No,Thur,Lunch,2
+12.26,2.0,No,Thur,Lunch,2
+18.26,3.25,No,Thur,Lunch,2
+8.51,1.25,No,Thur,Lunch,2
+10.33,2.0,No,Thur,Lunch,2
+14.15,2.0,No,Thur,Lunch,2
+16.0,2.0,Yes,Thur,Lunch,2
+13.16,2.75,No,Thur,Lunch,2
+17.47,3.5,No,Thur,Lunch,2
+34.3,6.7,No,Thur,Lunch,6
+41.19,5.0,No,Thur,Lunch,5
+27.05,5.0,No,Thur,Lunch,6
+16.43,2.3,No,Thur,Lunch,2
+8.35,1.5,No,Thur,Lunch,2
+18.64,1.36,No,Thur,Lunch,3
+11.87,1.63,No,Thur,Lunch,2
+9.78,1.73,No,Thur,Lunch,2
+7.51,2.0,No,Thur,Lunch,2
+14.07,2.5,No,Sun,Dinner,2
+13.13,2.0,No,Sun,Dinner,2
+17.26,2.74,No,Sun,Dinner,3
+24.55,2.0,No,Sun,Dinner,4
+19.77,2.0,No,Sun,Dinner,4
+29.85,5.14,No,Sun,Dinner,5
+48.17,5.0,No,Sun,Dinner,6
+25.0,3.75,No,Sun,Dinner,4
+13.39,2.61,No,Sun,Dinner,2
+16.49,2.0,No,Sun,Dinner,4
+21.5,3.5,No,Sun,Dinner,4
+12.66,2.5,No,Sun,Dinner,2
+16.21,2.0,No,Sun,Dinner,3
+13.81,2.0,No,Sun,Dinner,2
+17.51,3.0,Yes,Sun,Dinner,2
+24.52,3.48,No,Sun,Dinner,3
+20.76,2.24,No,Sun,Dinner,2
+31.71,4.5,No,Sun,Dinner,4
+10.59,1.61,Yes,Sat,Dinner,2
+10.63,2.0,Yes,Sat,Dinner,2
+50.81,10.0,Yes,Sat,Dinner,3
+15.81,3.16,Yes,Sat,Dinner,2
+7.25,5.15,Yes,Sun,Dinner,2
+31.85,3.18,Yes,Sun,Dinner,2
+16.82,4.0,Yes,Sun,Dinner,2
+32.9,3.11,Yes,Sun,Dinner,2
+17.89,2.0,Yes,Sun,Dinner,2
+14.48,2.0,Yes,Sun,Dinner,2
+9.6,4.0,Yes,Sun,Dinner,2
+34.63,3.55,Yes,Sun,Dinner,2
+34.65,3.68,Yes,Sun,Dinner,4
+23.33,5.65,Yes,Sun,Dinner,2
+45.35,3.5,Yes,Sun,Dinner,3
+23.17,6.5,Yes,Sun,Dinner,4
+40.55,3.0,Yes,Sun,Dinner,2
+20.69,5.0,No,Sun,Dinner,5
+20.9,3.5,Yes,Sun,Dinner,3
+30.46,2.0,Yes,Sun,Dinner,5
+18.15,3.5,Yes,Sun,Dinner,3
+23.1,4.0,Yes,Sun,Dinner,3
+15.69,1.5,Yes,Sun,Dinner,2
+19.81,4.19,Yes,Thur,Lunch,2
+28.44,2.56,Yes,Thur,Lunch,2
+15.48,2.02,Yes,Thur,Lunch,2
+16.58,4.0,Yes,Thur,Lunch,2
+7.56,1.44,No,Thur,Lunch,2
+10.34,2.0,Yes,Thur,Lunch,2
+43.11,5.0,Yes,Thur,Lunch,4
+13.0,2.0,Yes,Thur,Lunch,2
+13.51,2.0,Yes,Thur,Lunch,2
+18.71,4.0,Yes,Thur,Lunch,3
+12.74,2.01,Yes,Thur,Lunch,2
+13.0,2.0,Yes,Thur,Lunch,2
+16.4,2.5,Yes,Thur,Lunch,2
+20.53,4.0,Yes,Thur,Lunch,4
+16.47,3.23,Yes,Thur,Lunch,3
+26.59,3.41,Yes,Sat,Dinner,3
+38.73,3.0,Yes,Sat,Dinner,4
+24.27,2.03,Yes,Sat,Dinner,2
+12.76,2.23,Yes,Sat,Dinner,2
+30.06,2.0,Yes,Sat,Dinner,3
+25.89,5.16,Yes,Sat,Dinner,4
+48.33,9.0,No,Sat,Dinner,4
+13.27,2.5,Yes,Sat,Dinner,2
+28.17,6.5,Yes,Sat,Dinner,3
+12.9,1.1,Yes,Sat,Dinner,2
+28.15,3.0,Yes,Sat,Dinner,5
+11.59,1.5,Yes,Sat,Dinner,2
+7.74,1.44,Yes,Sat,Dinner,2
+30.14,3.09,Yes,Sat,Dinner,4
+12.16,2.2,Yes,Fri,Lunch,2
+13.42,3.48,Yes,Fri,Lunch,2
+8.58,1.92,Yes,Fri,Lunch,1
+15.98,3.0,No,Fri,Lunch,3
+13.42,1.58,Yes,Fri,Lunch,2
+16.27,2.5,Yes,Fri,Lunch,2
+10.09,2.0,Yes,Fri,Lunch,2
+20.45,3.0,No,Sat,Dinner,4
+13.28,2.72,No,Sat,Dinner,2
+22.12,2.88,Yes,Sat,Dinner,2
+24.01,2.0,Yes,Sat,Dinner,4
+15.69,3.0,Yes,Sat,Dinner,3
+11.61,3.39,No,Sat,Dinner,2
+10.77,1.47,No,Sat,Dinner,2
+15.53,3.0,Yes,Sat,Dinner,2
+10.07,1.25,No,Sat,Dinner,2
+12.6,1.0,Yes,Sat,Dinner,2
+32.83,1.17,Yes,Sat,Dinner,2
+35.83,4.67,No,Sat,Dinner,3
+29.03,5.92,No,Sat,Dinner,3
+27.18,2.0,Yes,Sat,Dinner,2
+22.67,2.0,Yes,Sat,Dinner,2
+17.82,1.75,No,Sat,Dinner,2
+18.78,3.0,No,Thur,Dinner,2
diff --git a/src-visual/tips.csv.txt b/src-visual/tips.csv.txt
new file mode 100644
index 0000000..ee9be5f
--- /dev/null
+++ b/src-visual/tips.csv.txt
@@ -0,0 +1,245 @@
+total_bill,tip,smoker,day,time,size
+16.99,1.01,No,Sun,Dinner,2
+10.34,1.66,No,Sun,Dinner,3
+21.01,3.5,No,Sun,Dinner,3
+23.68,3.31,No,Sun,Dinner,2
+24.59,3.61,No,Sun,Dinner,4
+25.29,4.71,No,Sun,Dinner,4
+8.77,2.0,No,Sun,Dinner,2
+26.88,3.12,No,Sun,Dinner,4
+15.04,1.96,No,Sun,Dinner,2
+14.78,3.23,No,Sun,Dinner,2
+10.27,1.71,No,Sun,Dinner,2
+35.26,5.0,No,Sun,Dinner,4
+15.42,1.57,No,Sun,Dinner,2
+18.43,3.0,No,Sun,Dinner,4
+14.83,3.02,No,Sun,Dinner,2
+21.58,3.92,No,Sun,Dinner,2
+10.33,1.67,No,Sun,Dinner,3
+16.29,3.71,No,Sun,Dinner,3
+16.97,3.5,No,Sun,Dinner,3
+20.65,3.35,No,Sat,Dinner,3
+17.92,4.08,No,Sat,Dinner,2
+20.29,2.75,No,Sat,Dinner,2
+15.77,2.23,No,Sat,Dinner,2
+39.42,7.58,No,Sat,Dinner,4
+19.82,3.18,No,Sat,Dinner,2
+17.81,2.34,No,Sat,Dinner,4
+13.37,2.0,No,Sat,Dinner,2
+12.69,2.0,No,Sat,Dinner,2
+21.7,4.3,No,Sat,Dinner,2
+19.65,3.0,No,Sat,Dinner,2
+9.55,1.45,No,Sat,Dinner,2
+18.35,2.5,No,Sat,Dinner,4
+15.06,3.0,No,Sat,Dinner,2
+20.69,2.45,No,Sat,Dinner,4
+17.78,3.27,No,Sat,Dinner,2
+24.06,3.6,No,Sat,Dinner,3
+16.31,2.0,No,Sat,Dinner,3
+16.93,3.07,No,Sat,Dinner,3
+18.69,2.31,No,Sat,Dinner,3
+31.27,5.0,No,Sat,Dinner,3
+16.04,2.24,No,Sat,Dinner,3
+17.46,2.54,No,Sun,Dinner,2
+13.94,3.06,No,Sun,Dinner,2
+9.68,1.32,No,Sun,Dinner,2
+30.4,5.6,No,Sun,Dinner,4
+18.29,3.0,No,Sun,Dinner,2
+22.23,5.0,No,Sun,Dinner,2
+32.4,6.0,No,Sun,Dinner,4
+28.55,2.05,No,Sun,Dinner,3
+18.04,3.0,No,Sun,Dinner,2
+12.54,2.5,No,Sun,Dinner,2
+10.29,2.6,No,Sun,Dinner,2
+34.81,5.2,No,Sun,Dinner,4
+9.94,1.56,No,Sun,Dinner,2
+25.56,4.34,No,Sun,Dinner,4
+19.49,3.51,No,Sun,Dinner,2
+38.01,3.0,Yes,Sat,Dinner,4
+26.41,1.5,No,Sat,Dinner,2
+11.24,1.76,Yes,Sat,Dinner,2
+48.27,6.73,No,Sat,Dinner,4
+20.29,3.21,Yes,Sat,Dinner,2
+13.81,2.0,Yes,Sat,Dinner,2
+11.02,1.98,Yes,Sat,Dinner,2
+18.29,3.76,Yes,Sat,Dinner,4
+17.59,2.64,No,Sat,Dinner,3
+20.08,3.15,No,Sat,Dinner,3
+16.45,2.47,No,Sat,Dinner,2
+3.07,1.0,Yes,Sat,Dinner,1
+20.23,2.01,No,Sat,Dinner,2
+15.01,2.09,Yes,Sat,Dinner,2
+12.02,1.97,No,Sat,Dinner,2
+17.07,3.0,No,Sat,Dinner,3
+26.86,3.14,Yes,Sat,Dinner,2
+25.28,5.0,Yes,Sat,Dinner,2
+14.73,2.2,No,Sat,Dinner,2
+10.51,1.25,No,Sat,Dinner,2
+17.92,3.08,Yes,Sat,Dinner,2
+27.2,4.0,No,Thur,Lunch,4
+22.76,3.0,No,Thur,Lunch,2
+17.29,2.71,No,Thur,Lunch,2
+19.44,3.0,Yes,Thur,Lunch,2
+16.66,3.4,No,Thur,Lunch,2
+10.07,1.83,No,Thur,Lunch,1
+32.68,5.0,Yes,Thur,Lunch,2
+15.98,2.03,No,Thur,Lunch,2
+34.83,5.17,No,Thur,Lunch,4
+13.03,2.0,No,Thur,Lunch,2
+18.28,4.0,No,Thur,Lunch,2
+24.71,5.85,No,Thur,Lunch,2
+21.16,3.0,No,Thur,Lunch,2
+28.97,3.0,Yes,Fri,Dinner,2
+22.49,3.5,No,Fri,Dinner,2
+5.75,1.0,Yes,Fri,Dinner,2
+16.32,4.3,Yes,Fri,Dinner,2
+22.75,3.25,No,Fri,Dinner,2
+40.17,4.73,Yes,Fri,Dinner,4
+27.28,4.0,Yes,Fri,Dinner,2
+12.03,1.5,Yes,Fri,Dinner,2
+21.01,3.0,Yes,Fri,Dinner,2
+12.46,1.5,No,Fri,Dinner,2
+11.35,2.5,Yes,Fri,Dinner,2
+15.38,3.0,Yes,Fri,Dinner,2
+44.3,2.5,Yes,Sat,Dinner,3
+22.42,3.48,Yes,Sat,Dinner,2
+20.92,4.08,No,Sat,Dinner,2
+15.36,1.64,Yes,Sat,Dinner,2
+20.49,4.06,Yes,Sat,Dinner,2
+25.21,4.29,Yes,Sat,Dinner,2
+18.24,3.76,No,Sat,Dinner,2
+14.31,4.0,Yes,Sat,Dinner,2
+14.0,3.0,No,Sat,Dinner,2
+7.25,1.0,No,Sat,Dinner,1
+38.07,4.0,No,Sun,Dinner,3
+23.95,2.55,No,Sun,Dinner,2
+25.71,4.0,No,Sun,Dinner,3
+17.31,3.5,No,Sun,Dinner,2
+29.93,5.07,No,Sun,Dinner,4
+10.65,1.5,No,Thur,Lunch,2
+12.43,1.8,No,Thur,Lunch,2
+24.08,2.92,No,Thur,Lunch,4
+11.69,2.31,No,Thur,Lunch,2
+13.42,1.68,No,Thur,Lunch,2
+14.26,2.5,No,Thur,Lunch,2
+15.95,2.0,No,Thur,Lunch,2
+12.48,2.52,No,Thur,Lunch,2
+29.8,4.2,No,Thur,Lunch,6
+8.52,1.48,No,Thur,Lunch,2
+14.52,2.0,No,Thur,Lunch,2
+11.38,2.0,No,Thur,Lunch,2
+22.82,2.18,No,Thur,Lunch,3
+19.08,1.5,No,Thur,Lunch,2
+20.27,2.83,No,Thur,Lunch,2
+11.17,1.5,No,Thur,Lunch,2
+12.26,2.0,No,Thur,Lunch,2
+18.26,3.25,No,Thur,Lunch,2
+8.51,1.25,No,Thur,Lunch,2
+10.33,2.0,No,Thur,Lunch,2
+14.15,2.0,No,Thur,Lunch,2
+16.0,2.0,Yes,Thur,Lunch,2
+13.16,2.75,No,Thur,Lunch,2
+17.47,3.5,No,Thur,Lunch,2
+34.3,6.7,No,Thur,Lunch,6
+41.19,5.0,No,Thur,Lunch,5
+27.05,5.0,No,Thur,Lunch,6
+16.43,2.3,No,Thur,Lunch,2
+8.35,1.5,No,Thur,Lunch,2
+18.64,1.36,No,Thur,Lunch,3
+11.87,1.63,No,Thur,Lunch,2
+9.78,1.73,No,Thur,Lunch,2
+7.51,2.0,No,Thur,Lunch,2
+14.07,2.5,No,Sun,Dinner,2
+13.13,2.0,No,Sun,Dinner,2
+17.26,2.74,No,Sun,Dinner,3
+24.55,2.0,No,Sun,Dinner,4
+19.77,2.0,No,Sun,Dinner,4
+29.85,5.14,No,Sun,Dinner,5
+48.17,5.0,No,Sun,Dinner,6
+25.0,3.75,No,Sun,Dinner,4
+13.39,2.61,No,Sun,Dinner,2
+16.49,2.0,No,Sun,Dinner,4
+21.5,3.5,No,Sun,Dinner,4
+12.66,2.5,No,Sun,Dinner,2
+16.21,2.0,No,Sun,Dinner,3
+13.81,2.0,No,Sun,Dinner,2
+17.51,3.0,Yes,Sun,Dinner,2
+24.52,3.48,No,Sun,Dinner,3
+20.76,2.24,No,Sun,Dinner,2
+31.71,4.5,No,Sun,Dinner,4
+10.59,1.61,Yes,Sat,Dinner,2
+10.63,2.0,Yes,Sat,Dinner,2
+50.81,10.0,Yes,Sat,Dinner,3
+15.81,3.16,Yes,Sat,Dinner,2
+7.25,5.15,Yes,Sun,Dinner,2
+31.85,3.18,Yes,Sun,Dinner,2
+16.82,4.0,Yes,Sun,Dinner,2
+32.9,3.11,Yes,Sun,Dinner,2
+17.89,2.0,Yes,Sun,Dinner,2
+14.48,2.0,Yes,Sun,Dinner,2
+9.6,4.0,Yes,Sun,Dinner,2
+34.63,3.55,Yes,Sun,Dinner,2
+34.65,3.68,Yes,Sun,Dinner,4
+23.33,5.65,Yes,Sun,Dinner,2
+45.35,3.5,Yes,Sun,Dinner,3
+23.17,6.5,Yes,Sun,Dinner,4
+40.55,3.0,Yes,Sun,Dinner,2
+20.69,5.0,No,Sun,Dinner,5
+20.9,3.5,Yes,Sun,Dinner,3
+30.46,2.0,Yes,Sun,Dinner,5
+18.15,3.5,Yes,Sun,Dinner,3
+23.1,4.0,Yes,Sun,Dinner,3
+15.69,1.5,Yes,Sun,Dinner,2
+19.81,4.19,Yes,Thur,Lunch,2
+28.44,2.56,Yes,Thur,Lunch,2
+15.48,2.02,Yes,Thur,Lunch,2
+16.58,4.0,Yes,Thur,Lunch,2
+7.56,1.44,No,Thur,Lunch,2
+10.34,2.0,Yes,Thur,Lunch,2
+43.11,5.0,Yes,Thur,Lunch,4
+13.0,2.0,Yes,Thur,Lunch,2
+13.51,2.0,Yes,Thur,Lunch,2
+18.71,4.0,Yes,Thur,Lunch,3
+12.74,2.01,Yes,Thur,Lunch,2
+13.0,2.0,Yes,Thur,Lunch,2
+16.4,2.5,Yes,Thur,Lunch,2
+20.53,4.0,Yes,Thur,Lunch,4
+16.47,3.23,Yes,Thur,Lunch,3
+26.59,3.41,Yes,Sat,Dinner,3
+38.73,3.0,Yes,Sat,Dinner,4
+24.27,2.03,Yes,Sat,Dinner,2
+12.76,2.23,Yes,Sat,Dinner,2
+30.06,2.0,Yes,Sat,Dinner,3
+25.89,5.16,Yes,Sat,Dinner,4
+48.33,9.0,No,Sat,Dinner,4
+13.27,2.5,Yes,Sat,Dinner,2
+28.17,6.5,Yes,Sat,Dinner,3
+12.9,1.1,Yes,Sat,Dinner,2
+28.15,3.0,Yes,Sat,Dinner,5
+11.59,1.5,Yes,Sat,Dinner,2
+7.74,1.44,Yes,Sat,Dinner,2
+30.14,3.09,Yes,Sat,Dinner,4
+12.16,2.2,Yes,Fri,Lunch,2
+13.42,3.48,Yes,Fri,Lunch,2
+8.58,1.92,Yes,Fri,Lunch,1
+15.98,3.0,No,Fri,Lunch,3
+13.42,1.58,Yes,Fri,Lunch,2
+16.27,2.5,Yes,Fri,Lunch,2
+10.09,2.0,Yes,Fri,Lunch,2
+20.45,3.0,No,Sat,Dinner,4
+13.28,2.72,No,Sat,Dinner,2
+22.12,2.88,Yes,Sat,Dinner,2
+24.01,2.0,Yes,Sat,Dinner,4
+15.69,3.0,Yes,Sat,Dinner,3
+11.61,3.39,No,Sat,Dinner,2
+10.77,1.47,No,Sat,Dinner,2
+15.53,3.0,Yes,Sat,Dinner,2
+10.07,1.25,No,Sat,Dinner,2
+12.6,1.0,Yes,Sat,Dinner,2
+32.83,1.17,Yes,Sat,Dinner,2
+35.83,4.67,No,Sat,Dinner,3
+29.03,5.92,No,Sat,Dinner,3
+27.18,2.0,Yes,Sat,Dinner,2
+22.67,2.0,Yes,Sat,Dinner,2
+17.82,1.75,No,Sat,Dinner,2
+18.78,3.0,No,Thur,Dinner,2
diff --git a/visual.ipynb b/visual.ipynb
new file mode 100644
index 0000000..ba137ad
--- /dev/null
+++ b/visual.ipynb
@@ -0,0 +1,1494 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "# Графическая визуализация данных\n",
+ "\n",
+ " \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",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Краткий пример использования `matplotlib`\n",
+ "\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",
+ "\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": [
+ "Полный каталог типов графиков можно найти на сайте .\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",
+ "\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",
+ "\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",
+ "\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",
+ "\n",
+ "\n",
+ "| Параметр | Описание |
\n",
+ "\n",
+ "\n",
+ " fname | Строка, содержащая путь к файлу или файлоподобный объект Python. Формат рисунка определяется расширением файла |
\n",
+ " dpi | Разрешение рисунка в точках на дюйм. По умолчанию 100 |
\n",
+ " facecolor, edgecolor | Цвет фона рисунка вне графика. По умолчанию w (белый) |
\n",
+ " format | Явное задание формата файла |
\n",
+ " bbox_inches | Часть рисунка для сохранения. Если задано 'tight', 2будет попытка обрезать пустое пространство вокруг |
\n",
+ "\n",
+ "
\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "# Построение графиков с помощью `pandas` и `seaborn`\n",
+ "\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",
+ "\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` \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Параметр | Описани |
\n",
+ "\n",
+ "\n",
+ " label | Метка для легенды |
\n",
+ " ax | Объект subplot из matplotlib, в который выводится график. Если не задан — вывод идет в активный подграфик |
\n",
+ " style | Строка, задающая стиль графика (например, ko--) |
\n",
+ " alpha | Прозрачность заполнения графика (от 0 до 1) |
\n",
+ " kind | Тип графика. Может быть: 'area' , 'bar' , 'barh' , 'density', 'hist' , 'kde' , 'line' , 'pie' |
\n",
+ " logy | Использовать ли логарифмический масштаб по оси y |
\n",
+ " use_index | Использовать ли объект индекс для меток оси |
\n",
+ " rot | Поворот меток оси |
\n",
+ " xticks | Значения для меток оси x |
\n",
+ " yticks | Значения для меток оси x |
\n",
+ " xlim | Границы по оси x (например, [0, 10]) |
\n",
+ " ylim | Границы по оси y |
\n",
+ " grid | Отображать ли сетку по осям (включено по умолчанию) |
\n",
+ "\n",
+ "
\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` \n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "| Параметр | Описание |
\n",
+ "\n",
+ "\n",
+ " subplots | Рисовать ли каждый столбец DataFrame в отдельном подграфике |
\n",
+ " sharex | Если subplots=True, использовать ли одну и ту же ось x, связывая метки оси |
\n",
+ " sharey | Если subplots=True, использовать ли одну и ту же ось y |
\n",
+ " figsize | Размер рисунка для создания в виде кортежа |
\n",
+ " title | Заголовок рисунка в виде строки |
\n",
+ " legend | Добавлять ли легенду на рисунок (по умолчанию True) |
\n",
+ " sort_columns | Отображать ли столбцы в алфавитном порядке |
\n",
+ "\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Столбчатые диаграммы\n",
+ "\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",
+ "\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",
+ "\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",
+ "\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",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ ""
+ ]
+ }
+ ],
+ "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
+}