{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Библиотеки NumPy, Matpotlib, pandas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В этой лекции мы вкратце познакомимся с тремя основными библиотеками для решения научных задач. Они не являются частью стандартной библиотеки, и в общем случае должны устанавливаться вручную. Однако поскольку мы использовали дистрибутив Anaconda для установки Python, нам не потребуется ничего делать дополнительно, так как он включает в себя все нужное." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Содержание лекции" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* [NumPy](#NumPy)\n", " * [Создание массива](#Создание-массива)\n", " * [Получение среза](#Получение-среза)\n", " * [Изменение формы](#Изменение-формы)\n", " * [Операции и универсальные функции](#Операции-и-универсальные-функции)\n", "* [Matplotlib](#Matplotlib)\n", " * [График](#График)\n", " * [Диаграмма разброса](#Диаграмма-разброса)\n", " * [Гистограмма](#Гистограмма)\n", "* [pandas](#pandas)\n", " * [Класс Series](#Класс-Series)\n", " * [Класс DataFrame](#Класс-DataFrame)\n", " * [Статистика](#Статистика)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## NumPy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Библиотека [NumPy](https://docs.scipy.org/doc/numpy/reference/) предоставляет типы и функции для вычислений с многомерными **массивами**. Массивом (англ. *array*) в программировании называется контейнер, хранящий последовательно друг за другом множество элементов. Из тех контейнеров, с которыми мы познакомились с вами в одной из предыдущих лекций, он больше всего похож на [список](09_Collections.ipynb#Список). Основное же отличие заключается в том, что массив может хранить только значения фиксированного типа - того, который был указан при его создании. Благодаря этому ограничению можно эффективнее организовать хранение в памяти элементов массива, и добиться хорошей производительности операций, выполняющихся над всеми элементами." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Элементами многомерного массива являются другие массивы. Классический пример - матрица, представляющая собой массив строк, каждая из которых является массивом чисел." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Основным типом данных, предоставляемым библиотекой NumPy, является класс `ndarray`, который описывает многомерный массив. Перечислим наиболее важные атрибуты экземпляров этого класса:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. `ndim` - количество измерений или, как их принято называть, осей. Например, обычная матрица имеет две оси (строки и столбцы). Оси идентифицируются своим порядковым номером, причем как и для индексов последовательностей, нумерация начинается с нуля (у матрицы строки - это нулевая ось, а столбцы - первая).\n", "2. `shape` - форма массива. Это кортеж, который для каждой оси содержит число элементов в ней. Например, если у нас есть матрица размерности $N \\times M$, то `shape` будет равно `(N, M)`.\n", "3. `size` - общее количество элементов в многомерном массиве. По сути, представляет собой произведение всех элементов `shape`.\n", "4. `dtype` - объект, содержащий информацию о типе данных элементов массива." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В дальнейших примерах нам часто будет требоваться выводить информацию о массиве на экран, поэтому мы определим простую функцию для этого:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "def print_array(a):\n", " print('ndim={}, shape={}, size={}, dtype={}'.format(a.ndim, a.shape, a.size, a.dtype))\n", " print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Создание массива" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Существует несколько способов создать массив. Один из них - использовать функцию `array`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(3,), size=3, dtype=int32\n", "[1 2 3]\n" ] } ], "source": [ "# создаем одномерный массив\n", "a = np.array([1, 2, 3])\n", "print_array(a)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(2, 4), size=8, dtype=float64\n", "[[0.1 0.2 0.3 0.4]\n", " [0.5 0.6 0.7 0.8]]\n" ] } ], "source": [ "# создаем двумерный массив (матрицу)\n", "a = np.array([[0.1, 0.2, 0.3, 0.4],\n", " [0.5, 0.6, 0.7, 0.8]])\n", "print_array(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если при создании массива не указывается тип его элементов, то функция `array` в качестве него выбирает такой, чтобы можно было хранить любой элемент из перечисленных в ее вызове:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(3,), size=3, dtype=int32\n", "[1 2 3]\n" ] } ], "source": [ "a = np.array([1, 2, 3])\n", "print_array(a)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(3,), size=3, dtype=float64\n", "[1. 2. 3.1]\n" ] } ], "source": [ "a = np.array([1, 2, 3.1])\n", "print_array(a)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(3,), size=3, dtype=complex128\n", "[1.+0.j 2.+0.j 3.+0.j]\n" ] } ], "source": [ "# явно указываем тип элементов\n", "a = np.array([1, 2, 3], dtype=complex)\n", "print_array(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Библиотека NumPy для элементов массива использует собственные типы данных, которые можно использовать так же, как соответствующие встроенные. Особенность типов данных из NumPy в том, что для них четко определено количество бит, которое они занимают в памяти. Можно при создании массива указать и тип данных из библиотеки NumPy:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(3,), size=3, dtype=int16\n", "[1 2 3]\n" ] } ], "source": [ "# используем 16битовые целые числа для хранения элементов\n", "a = np.array([1, 2, 3], dtype=np.int16)\n", "print_array(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Важно при этом понимать, какой диапазон значений можно хранить в том или ином типе (например, для int16 это $[-32768, 32767]$), потому что если впоследствии ваша программа присвоит элементу массива значение вне этого диапазона, оно будет сохранено неправильно!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Часто бывает так, что при создании массива известная его форма, но не значения элементов. В этом случае можно воспользоваться функциями `zeros`, `ones` или `empty`, которые заполняют созданный массив нулями, единицами или случайными значениями. В качестве первого аргумента все эти функции принимают кортеж, описывающий форму массива:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=3, shape=(2, 3, 4), size=24, dtype=float64\n", "[[[0. 0. 0. 0.]\n", " [0. 0. 0. 0.]\n", " [0. 0. 0. 0.]]\n", "\n", " [[0. 0. 0. 0.]\n", " [0. 0. 0. 0.]\n", " [0. 0. 0. 0.]]]\n" ] } ], "source": [ "# создаем массив с 3мя осями;\n", "# он представляет собой массив из двух массивов, каждый из\n", "# которых содержит 3 массива, каждый из которых содержит 4 элемента\n", "a = np.zeros((2, 3, 4))\n", "print_array(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обратите внимание, что по умолчанию для элементов массива используется тип `float64`. С помощью именованного параметра `dtype` функции `zeros` и других можно указать желаемый тип элементов." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Наконец, библиотека NumPy предоставляет функцию `arange` для генерации числовой последовательности, аналогичную встроенной функции `range`. Отличие заключается в том, что с помощью `arange` можно генерировать и последовательности чисел с плавающей точкой." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(10,), size=10, dtype=int32\n", "[0 1 2 3 4 5 6 7 8 9]\n" ] } ], "source": [ "# целые из интервала [0, 10) с шагом 1\n", "a = np.arange(10)\n", "print_array(a)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(10,), size=10, dtype=float64\n", "[0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]\n" ] } ], "source": [ "# действительные из интервала [0.0, 1.0) c шагом 0.1\n", "a = np.arange(0, 1, 0.1)\n", "print_array(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Заметим, что использовать функцию `arange` для получения действительных чисел, стоит осторожно, потому что размер полученного массива может отличаться от ожидаемого (это связано с неточным представлением [чисел с плавающей точкой](04_Data_Types.ipynb#Типы-с-плавающей-точкой)). Более безопасной с этой точки зрения является функция `linspace`, которая возвращает указанное количество равноудаленных друг от друга чисел из интервала:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(10,), size=10, dtype=float64\n", "[0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]\n" ] } ], "source": [ "# 10 равноудаленных друг от друга чисел из интервала [0, 0.9]\n", "a = np.linspace(0, 0.9, 10)\n", "print_array(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Получение среза" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В случае одномерных массивов, получение срезов выполняется так же, как и для обычных последовательностей (списков, кортежей и т.д.). У многомерных массивов индексироваться может каждая ось. Если при этом отсутствует индекс для некоторой оси, то возвращаются все ее элементы. Срез объекта типа `ndarray` также имеет тип `ndarray`." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n" ] } ], "source": [ "a_multi = np.array([[0, 1, 2],\n", " [3, 4, 5],\n", " [6, 7, 8],\n", " [9, 10, 11]])\n", "\n", "# выводи третий элемент второй строки (помните, что нумерация\n", "# индексов начинается с нуля!)\n", "print(a_multi[1, 2]) " ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "[[3 4 5]\n", " [6 7 8]]\n" ] } ], "source": [ "# получаем срез, состоящий из второй и третьей строки\n", "result = a_multi[1:3]\n", "print(type(result))\n", "print(result)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 9 11]\n", " [ 3 5]]\n" ] } ], "source": [ "# получаем срез, состоящий из первого и третьего элемента\n", "# второй и четвертой строки, взятых в обратном порядке\n", "print(a_multi[3:0:-2, 0:3:2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Тип `ndarray` является итерируемым, поэтому его можно использовать в цикле `for ... in`. Итерация при этом происходит по первой оси (например, в случае матриц - по строкам):" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 1 2]\n", "[3 4 5]\n", "[6 7 8]\n", "[ 9 10 11]\n" ] } ], "source": [ "for row in a_multi:\n", " print(row)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Для итерации по элементам нужно использовать атрибут `flat`:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n", "10\n", "11\n" ] } ], "source": [ "for item in a_multi.flat:\n", " print(item)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обратите внимание, что при итерации по элементам вначале изменяется последняя ось, потом предпоследняя и т.д. Например, для трехмерного массива $N_1 \\times N_2 \\times N_3$ элементы извлекались бы в такой последовательности:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n",
    "a[0][0][0], ..., a[0][0][N3], a[0][1][0], ..., a[0][N2][N3], a[1][0][0], ..., a[N1][N2][N3]\n",
    "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Поскольку `ndarray` относится к изменяемым типам данных, его элементы можно модифицировать:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[100 1 2]\n", " [ 0 0 0]\n", " [ 20 21 22]\n", " [ 9 10 11]]\n" ] } ], "source": [ "a_multi[0, 0] = 100 # присваиваем первому элементу 100\n", "a_multi[1] = 0 # присваиваем всем элементам второй строки 0\n", "a_multi[2] = np.arange(20, 23) # заменяем третью строку на строку [20, 21, 22]\n", "\n", "print(a_multi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Изменение формы" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Класс `ndarray` предоставляет несколько методов и атрибутов, которые изменяют форму массива (количество и размер осей):" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "|
Название
| Описание |\n", "|----------------------------------|----------|\n", "|
reshape(shape, ...)
| Возвращает новый массив с теми же данными, но с формой shape |\n", "|
resize(shape, ...)
| Изменяет форму текущего массива на shape |\n", "|
ravel(...)
| Возвращает \"плоскую\" версию массива с одним измерением |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "При заполнении нового массива, его первому элементу присваивается первый элемент старого, второму - второй и т.д. Причем порядок элементов соответствует тому, в котором они возвращались бы при итерации по всем элементам (по атрибуту `flat`)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Еще класс `ndarray` предоставляет метод `transpose` и атрибут `T`, которые позволяют получить транспонированную версию многомерного массива." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "a1 = np.arange(10)\n", "a2 = a1.reshape((2, 5))\n", "a3 = a2.T\n", "a4 = a3.ravel()" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(10,), size=10, dtype=int32\n", "[0 1 2 3 4 5 6 7 8 9]\n" ] } ], "source": [ "print_array(a1)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(2, 5), size=10, dtype=int32\n", "[[0 1 2 3 4]\n", " [5 6 7 8 9]]\n" ] } ], "source": [ "print_array(a2)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(5, 2), size=10, dtype=int32\n", "[[0 5]\n", " [1 6]\n", " [2 7]\n", " [3 8]\n", " [4 9]]\n" ] } ], "source": [ "print_array(a3)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=1, shape=(10,), size=10, dtype=int32\n", "[0 5 1 6 2 7 3 8 4 9]\n" ] } ], "source": [ "print_array(a4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Для объединения нескольких многомерных массивов в один класс `ndarray` предоставляет следующие функции:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "|
Название
| Описание |\n", "|----------------------------------|----------|\n", "|
hstack(arrays_seq)
| Возвращает новый массив, каждая строка которого является конкатенацией строк массивов из последовательности arrays_seq |\n", "|
vstack(arrays_seq)
| Возвращает новый массив, каждый столбец которого является конкатенацией столбцов массивов из последовательности arrays_seq |" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "a1 = np.array([[1, 2, 3],\n", " [4, 5, 6],\n", " [7, 8, 9]])\n", "a2 = np.array([[11, 12],\n", " [13, 14],\n", " [15, 16]])\n", "a3 = np.array([[11, 12, 13],\n", " [14, 15, 16]])" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(3, 5), size=15, dtype=int32\n", "[[ 1 2 3 11 12]\n", " [ 4 5 6 13 14]\n", " [ 7 8 9 15 16]]\n" ] } ], "source": [ "print_array(np.hstack([a1, a2]))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(5, 3), size=15, dtype=int32\n", "[[ 1 2 3]\n", " [ 4 5 6]\n", " [ 7 8 9]\n", " [11 12 13]\n", " [14 15 16]]\n" ] } ], "source": [ "print_array(np.vstack((a1, a3)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Для разбиения многомерного массива на несколько меньших, используются функции `hsplit` и `vsplit`. Если им передается числовой аргумент, то он трактуется как количество массивов, на которое нужно разбить исходный, а если последовательность, то ее элементы трактуются как индексы, по которым нужно производить разбиение:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(2, 9), size=18, dtype=int32\n", "[[ 0 1 2 3 4 5 6 7 8]\n", " [ 9 10 11 12 13 14 15 16 17]]\n" ] } ], "source": [ "a = np.arange(18)\n", "a.resize(2, 9)\n", "print_array(a)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(2, 3), size=6, dtype=int32\n", "[[ 0 1 2]\n", " [ 9 10 11]]\n", "ndim=2, shape=(2, 3), size=6, dtype=int32\n", "[[ 3 4 5]\n", " [12 13 14]]\n", "ndim=2, shape=(2, 3), size=6, dtype=int32\n", "[[ 6 7 8]\n", " [15 16 17]]\n" ] } ], "source": [ "arrays = np.hsplit(a, 3)\n", "\n", "for array in arrays:\n", " print_array(array)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(2, 2), size=4, dtype=int32\n", "[[ 0 9]\n", " [ 1 10]]\n", "ndim=2, shape=(3, 2), size=6, dtype=int32\n", "[[ 2 11]\n", " [ 3 12]\n", " [ 4 13]]\n", "ndim=2, shape=(3, 2), size=6, dtype=int32\n", "[[ 5 14]\n", " [ 6 15]\n", " [ 7 16]]\n", "ndim=2, shape=(1, 2), size=2, dtype=int32\n", "[[ 8 17]]\n" ] } ], "source": [ "arrays = np.vsplit(a.T, [2, 5, 8])\n", "\n", "for array in arrays:\n", " print_array(array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Операции и универсальные функции" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обычные операции в Python перегружены для массива и при выполнении действуют на все его элементы:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(3, 4), size=12, dtype=int32\n", "[[ 0 1 2 3]\n", " [ 4 5 6 7]\n", " [ 8 9 10 11]]\n" ] } ], "source": [ "a = np.arange(12).reshape((3, 4))\n", "print_array(a)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1 2 3 4]\n", " [ 5 6 7 8]\n", " [ 9 10 11 12]]\n" ] } ], "source": [ "a += 1\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если в качестве операндов используются два массива одинаковой размерности, то операция выполняется для всех пар элементов на соответствующих позициях, например:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(2, 2), size=4, dtype=int32\n", "[[7 6]\n", " [5 4]]\n", "ndim=2, shape=(2, 2), size=4, dtype=int32\n", "[[0 1]\n", " [2 3]]\n" ] } ], "source": [ "a1 = np.arange(7, 3, -1).reshape(2, 2)\n", "a2 = np.arange(4).reshape(2, 2)\n", "\n", "print_array(a1)\n", "print_array(a2)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 6]\n", " [10 12]]\n", "[[ 1 6]\n", " [25 64]]\n" ] } ], "source": [ "print(a1 * a2)\n", "print(a1 ** a2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если вместо поэлементного умножения вы хотите матричное, то нужно воспользоваться функцией `dot`:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(2, 3), size=6, dtype=int32\n", "[[0 1 2]\n", " [3 4 5]]\n", "ndim=2, shape=(3, 2), size=6, dtype=int32\n", "[[0 1]\n", " [2 3]\n", " [4 5]]\n", "ndim=2, shape=(2, 2), size=4, dtype=int32\n", "[[10 13]\n", " [28 40]]\n" ] } ], "source": [ "a1 = np.arange(6).reshape(2, 3)\n", "a2 = np.arange(6).reshape(3, 2)\n", "\n", "print_array(a1)\n", "print_array(a2)\n", "print_array(np.dot(a1, a2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Методы `sum`, `max` и `min`, определенные для встроенных коллекций Python, также определены и для класса `ndarray`. По умолчанию они работают со всеми элементами массива, но можно также указать конкретную ось, вдоль которой производить вычисления." ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(3, 2), size=6, dtype=int32\n", "[[0 1]\n", " [2 3]\n", " [4 5]]\n" ] } ], "source": [ "a = np.arange(6).reshape(3, 2)\n", "print_array(a)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "max=5, min=0\n", "[1 5 9]\n" ] } ], "source": [ "print('max={}, min={}'.format(a.max(), a.min()))\n", "\n", "# вычисляем по столбцам (axis=1), следовательно в результате\n", "# получим сумму элементов для каждой строки\n", "print(a.sum(axis=1)) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В модуле `numpy.random` содержатся функции для генерации случайных массивов произвольной размерности. Например, функция `random` из этого модуля создает массив указанной формы и заполняет его случайными числами, равномерно распределенными в интервале $[0, 1)$:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ndim=2, shape=(3, 3), size=9, dtype=float64\n", "[[0.77627538 0.82548991 0.27186471]\n", " [0.85898985 0.95649778 0.16657402]\n", " [0.16242193 0.62604804 0.69467224]]\n" ] } ], "source": [ "a = np.random.random((3, 3))\n", "print_array(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В NumPy реализованы те же математические функции, что встречаются в стандартной библиотеке Python, однако они дополнительно умеют работать с массивами. В терминологии библиотеки NumPy эти функции назваются **универсальными**." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1. 2. 3.]\n", " [4. 5. 6.]]\n" ] } ], "source": [ "a = np.array([[1, 4, 9],\n", " [16, 25, 36]])\n", "print(np.sqrt(a))" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.8660254037844386\n", "[0. 0.5 0.70710678 0.8660254 1. ]\n" ] } ], "source": [ "a = np.array([0, 30, 45, 60, 90], dtype=float) # градусы\n", "a *= np.pi / 180 # преобразуем в радианы\n", "\n", "# вычисляем синус для обычного числа и для массива\n", "print(np.sin(a[3]))\n", "print(np.sin(a))" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.72009011 0.50335114 0.09270624 0.58830524 0.96991841 0.52659037\n", " 0.0770578 0.28066821 0.67652392 0.83184407]\n", "mean: 0.5267055502037943\n", "variance: 0.08048031288469937\n" ] } ], "source": [ "a = np.random.random(10)\n", "print(a)\n", "\n", "print('mean:',np.mean(a)) # вычисляем математическое ожидание\n", "print('variance:', np.var(a)) # вычисляем дисперсию" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Matplotlib" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Библиотека [Matplotlib](https://matplotlib.org/) используется для создания различных 2D и 3D графиков и диаграмм, среди которых:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* обычные графики (англ. *line plot*)\n", "* диаграммы разброса/рассеивания (англ. *scatter plot*), характеризующие корреляцию между различными факторами\n", "* гистограммы (англ. *histogram*)\n", "* столбчатые диаграммы (англ. *bar chart*)\n", "* круговые диаграммы (англ. *pie chart*)\n", "* и другие" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Функции и типы Matplotlib умеют работать с массивами NumPy, и более того, практически никогда не используются без них. В библиотеке Matplotlib релиазовано два интерфейса - один процедурный, другой объектно-ориентированный. Мы будем использовать процедурный, который реализован в модуле `matplotlib.pyplot`. Давайте импортируем модули, которые мы будем использовать в примерах в этом разделе." ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### График" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обычный график создается с помощью функции `plot`. Основными ее параметрами являются две последовательности: в первой содержатся абсциссы точек, а во второй их ординаты. Функция `plot` строит график таким образом, чтобы он проходил через эти точки. Это означает, что чем сложнее форма графика, тем больше точек нужно передать в `plot`. Например, для построения прямой достаточно двух точек, но этого явно мало, чтобы правильно нарисовать параболу." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Кроме координат точек, функция `plot` имеет множество других параметров для настройки того, как график будет выглядеть. В наших примерах мы познакомим вас с некоторыми из них, а полную информацию можно получить в [справочном руководстве](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Давайте начнем с простого примера и создадим график прямой линии $2x + 1$:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# двух точек достаточно для того, чтобы построить прямую\n", "\n", "x = [0, 2] # ординаты\n", "y = [1, 5] # абсциссы\n", "\n", "plt.plot(x, y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Заметим, что сама функция `plot` не рисует график, а просто инициализирует нужную информацию для этого. В среде Jupyter Notebook по умолчанию используется режим, при котором вывод графика на экран происходит автоматически при выполнении ячейки, но вообще говоря, за это отвечает отдельная функция `show`. Если вы при работе с Matplotlib столкнетесь с ситуацией, когда график не отображается, в первую очередь стоит попробовать вызвать эту функцию." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Давайте немного иначе настроим наш график, чтобы продемонстрировать некоторые возможности Matplotlib:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x = np.array([0, 2])\n", "y = np.array([1, 5])\n", "\n", "# задаем дополнительно цвет линии и толщину\n", "plt.plot(x, y, color='red', linewidth=2.5)\n", "\n", "# установим границы осей X и Y так, чтобы график не\n", "# выглядел \"зажатым\" осями координат\n", "plt.xlim(x.min() - 0.5, x.max() + 0.5)\n", "plt.ylim(y.min() - 0.5, y.max() + 0.5)\n", "\n", "# определим, какие точки будут отмечены на осях\n", "x_ticks = np.linspace(x.min(), x.max(), 2)\n", "y_ticks = np.linspace(y.min(), y.max(), 2)\n", "plt.xticks(x_ticks)\n", "plt.yticks(y_ticks)\n", "\n", "# определим, как будут подписаны координатные оси\n", "plt.xlabel('abscissa')\n", "plt.ylabel('ordinate')\n", "\n", "# рисуем график\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Можно в одной системе координат отобразить сразу несколько графиков. Давайте попробуем вывести графики синуса и косинуса." ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x = np.linspace(-np.pi, np.pi, 200)\n", "cos_x = np.cos(x)\n", "sin_x = np.sin(x)\n", "\n", "# добавляем два графика, устанавливаем для них цвет, тип линии\n", "# и название\n", "plt.plot(x, cos_x, color='red', linestyle='dashed', label='cosine')\n", "plt.plot(x, sin_x, color='green', linestyle='dotted', label='sine')\n", "\n", "# добавляем легеду (информацию о том, какая линия что означает)\n", "plt.legend()\n", "\n", "# определяем, какие точки будут отмечены на осях\n", "# можно в качестве значения указывать LaTeX-формулу (используем\n", "# это для того, чтобы вместо, например, 3.1415.. было написано pi)\n", "x_ticks = np.array([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])\n", "x_ticks_name = [r'$-\\pi$', r'$-\\pi/2$', r'$0$', r'$\\pi/2$', r'$\\pi$']\n", "y_ticks = np.array([-1, -0.5, 0, 0.5, 1])\n", "y_ticks_name = [r'$-1$', r'$-0.5$', r'$0$', r'$0.5$', r'$1$']\n", "\n", "plt.xticks(x_ticks, x_ticks_name)\n", "plt.yticks(y_ticks, y_ticks_name)\n", "\n", "# рисуем график\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теперь давайте попробуем настроить координатные оси таким образом, чтобы центр графика находился в точке $(0, 0)$, как мы привыкли со школы. Для этого нам потребуется метод `gca`, возвращающий объект, который можно использовать для управления внешним видом координатных осей. На рисунке сверху есть четыре оси, образующих прямоугольник, внутри которого находятся графики. Нам нужно скрыть две из них (например, ту, что сверху и ту, что справа), а оставшиеся две поместить в точку $(0, 0)$:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x = np.linspace(-np.pi, np.pi, 200)\n", "cos_x = np.cos(x)\n", "sin_x = np.sin(x)\n", "\n", "# добавляем два графика, устанавливаем для них цвет, тип линии\n", "# и название\n", "plt.plot(x, cos_x, color='red', linestyle='dashed', label='cosine')\n", "plt.plot(x, sin_x, color='green', linestyle='dotted', label='sine')\n", "\n", "# добавляем легеду (информацию о том, какая линия что означает)\n", "plt.legend()\n", "\n", "# определяем, какие точки будут отмечены на осях\n", "# можно в качестве значения указывать LaTex-формулу (используем\n", "# это для того, чтобы вместо, например, 3.1415.. было написано pi)\n", "x_ticks = np.array([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])\n", "x_ticks_name = [r'$-\\pi$', r'$-\\pi/2$', r'$0$', r'$\\pi/2$', r'$\\pi$']\n", "y_ticks = np.array([-1, -0.5, 0, 0.5, 1])\n", "y_ticks_name = [r'$-1$', r'$-0.5$', r'$0$', r'$0.5$', r'$1$']\n", "\n", "plt.xticks(x_ticks, x_ticks_name)\n", "plt.yticks(y_ticks, y_ticks_name)\n", "\n", "# меняем положение координатных осей\n", "axes = plt.gca()\n", "\n", " # скрываем две оси\n", "axes.spines['top'].set_color(None)\n", "axes.spines['right'].set_color(None)\n", "\n", " # устаналиваем позицию левой и правой оси;\n", " # data' означает, что 0 - это координата, через которую должна проходить ось\n", "axes.spines['left'].set_position(('data', 0))\n", "axes.spines['bottom'].set_position(('data', 0))\n", "\n", "# рисуем график\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Диаграмма разброса" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Диаграмма разброса используется тогда, когда нужно оценить корреляцию между несколькими факторами. Для примера, в качестве одного фактора мы возьмем просто случайные, ничего не означающие данные. Второй фактор мы получим как сумму первого и некоторой случайной величины с достаточно большой дисперсией. Очевидно, что между этими двумя значениями мы должны увидеть положительную корреляцию - с ростом одного, увеличивается и второе. Проверим это на практике:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from random import uniform\n", "from random import normalvariate\n", "\n", "# используем генератор, чтобы создать массив случайных данных\n", "x = np.array([uniform(0, 100) for i in range(1000)])\n", "y = np.array([item + normalvariate(0, 20) for item in x])\n", "\n", "# строим диаграмму разброса\n", "plt.scatter(x, y)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Несмотря на то, что мы выбрали большое значение стандартного отклонения для случайной величины, с помощью которой мы оказывали влияние на первый фактор, положительная корреляция видна невооруженным глазом: с ростом $x$ возрастает $y$. Если стандартное отклонение продолжить увеличивать, то в определенный момент корреляция, очевидно, пропадет. Убедитесь в этом сами." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Гистограмма" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Гистограммы часто используются для того, чтобы сделать предположение о том, какому распределению подчиняется случайная выборка: по выборке строится гистограмма, а затем сравнивается, плотность распределения какого закона она напоминает больше всего. В качестве примера, рассмотрим выборку из нормального закона распределения, но вообразим, что нам это неизвестно:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from math import sqrt\n", "from random import normalvariate\n", "\n", "def norm_density(x, mean, std):\n", " tmp1 = 1 / (std * np.sqrt(2 * np.pi))\n", " tmp2 = -((x - mean)**2 / 2 * std**2)\n", " return tmp1 * (np.e ** tmp2)\n", "\n", "\n", "x = np.array([normalvariate(3, 1) for i in range(10000)])\n", "\n", "# добавляем гистограмму на график (bins - количество столбиков в ней)\n", "plt.hist(x, bins=15, density=True)\n", "\n", "# добавим еще для наглядности график плотности распределения\n", "x_mean = np.mean(x)\n", "x_std = np.std(x) # стандартное отклонение\n", "density_x = np.linspace(x.min(), x.max(), 200)\n", "density_y = np.array([norm_density(item, x_mean, x_std) for item in density_x])\n", "plt.plot(density_x, density_y, linewidth=2.5, color='red')\n", "\n", "# рисуем графики\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Как видите, гистограмма, построенная по выборке из \"неизвестной\" случайной величины, по форме похожа на плотность нормального распределения. Исходя из этого можно сделать вывод, что \"неизвестная\" случайная величина имеет закон распределения, близкий к нормальному." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В заключение дадим очень полезную [ссылку](https://matplotlib.org/tutorials/index.html) на раздел документации библиотеки Matplotlib, по которой можно найти большое количество примеров графиков вместе с исходным кодом, строящим их. Примеры оттуда позволяют увидеть весь спектр возможностей Matplotlib." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## pandas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Библиотека [pandas](https://pandas.pydata.org/pandas-docs/stable/index.html) предоставляет классы для быстрой обработки и анализа больших объемов данных. В своей реализации она использует библиотеку NumPy, с которой мы познакомились чуть выше. Двумя важнейшими классами библиотеки pandas являются `Series` и `DataFrame`. Оба они представляют собой массивы, элементам которых назначены специальные **метки** (англ. *label*), в совокупности образующие **индекс** этого массива. Термин \"индекс\" из pandas пересекается с тем, что мы использовали для обозначения позиции элемента в последовательности. Обычно путаницы из-за этого не возникает, но вам стоит иметь это в виду." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Все элеметы массивов pandas приводятся к одному и тому же типу данных (используются типы из библиотеки NumPy)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Перед тем как начать использование библиотеки pandas, подключим необходимый модуль:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Класс Series" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Series` представляет собой изменяемый одномерный массив, к каждому элементу которого прикреплена произвольная метка. Объект класса `Series` можно создать несколькими способами:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 1\n", "1 2\n", "2 3\n", "3 4\n", "4 5\n", "dtype: int64\n" ] } ], "source": [ "# из обычного списка\n", "s = pd.Series([1, 2, 3, 4, 5])\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 0.825980\n", "1 0.605343\n", "2 0.690893\n", "dtype: float64\n" ] } ], "source": [ "# из ndarray\n", "s = pd.Series(np.random.random((3)))\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обратите внимание на первый столбец в выведенных на экран объектах `Series` - это и есть их индекс. Обратиться к нему можно с помощью атрибута `index`:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "RangeIndex(start=0, stop=3, step=1)\n" ] } ], "source": [ "print(s.index)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "По умолчанию индекс представляет собой последовательно возрастающие от нуля числа, но это легко можно изменить, явно указав метки:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Index(['first', 'second', 'third'], dtype='object')\n", "first 1\n", "second 2\n", "third 3\n", "dtype: int64\n" ] } ], "source": [ "s = pd.Series([1, 2, 3], index=['first', 'second', 'third'])\n", "print(s.index)\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Одномерный массив можно создать с помощью словаря Python, при этом ключи становятся метками, а значения - элементами:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 100\n", "b 200\n", "c 300\n", "dtype: int64\n" ] } ], "source": [ "s = pd.Series({'a':100, 'b':200, 'c':300})\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Объекты класса `Series` могут использовать как `ndarray` или как `dict`:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "5\n", "True\n" ] } ], "source": [ "s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])\n", "\n", "# получаем элемент по его позиции, как для ndarray\n", "print(s[1])\n", "\n", "# обращаемся к элементу по метке, как для dict\n", "print(s['e'])\n", "\n", "# определяем, есть ли метка в объекте Series\n", "print('c' in s)" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "d 4\n", "c 3\n", "dtype: int64\n" ] } ], "source": [ "# получаем срез, как для ndarray;\n", "# срез объекта Series тоже имеет тип Series\n", "print(s[3:1:-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Бинарные операции для одномерных массивов pandas работают так же, как и для массивов NumPy (применяются для каждого элемента). Универсальные функции NumPy могут в качестве аргумента принимать объекты `Series`:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 1\n", "b 2\n", "c 3\n", "dtype: int64 \n", "\n", "a 0.1\n", "b 0.2\n", "c 0.3\n", "dtype: float64\n" ] } ], "source": [ "s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])\n", "s2 = pd.Series([0.1, 0.2, 0.3], index=['a', 'b', 'c'])\n", "print(s1, '\\n')\n", "print(s2)" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 3\n", "b 6\n", "c 9\n", "dtype: int64 \n", "\n", "a 1.1\n", "b 2.2\n", "c 3.3\n", "dtype: float64 \n", "\n", "a 2.718282\n", "b 7.389056\n", "c 20.085537\n", "dtype: float64\n" ] } ], "source": [ "print(s1 * 3, '\\n')\n", "print(s1 + s2, '\\n')\n", "print(np.exp(s1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Особо стоит отметить случай, когда бинарная операция выполняется для массивов `Series`, имеющих разные метки. В этом случае происходит следующее: если метка есть в обоих массивах, то операция выполняется и ее результат становится значением элемента в новом объекте, иначе - в новый объект записывается специальная константа `Nan`, которая трактуется как отсутствие значения." ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x 0.1\n", "a 0.2\n", "c 0.3\n", "dtype: float64\n" ] } ], "source": [ "s2.index = ['x', 'a', 'c'] # меняем индекс у объекта s2\n", "print(s2)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 0.8\n", "b NaN\n", "c 2.7\n", "x NaN\n", "dtype: float64\n" ] } ], "source": [ "result = s1 - s2\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Любые бинарные арифметические операции со значениями `Nan` будут давать `Nan`:" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 1.8\n", "b NaN\n", "c 3.7\n", "x NaN\n", "dtype: float64\n" ] } ], "source": [ "print(result + 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Объекты типа `Series` поддерживают обращение сразу к нескольким элементам:" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a 1\n", "d 4\n", "e 5\n", "dtype: int64 \n", "\n", "a 1\n", "b 2\n", "c 0\n", "d 0\n", "e 5\n", "dtype: int64\n" ] } ], "source": [ "s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])\n", "print(s[['a', 'd', 'e']], '\\n')\n", "\n", "# изменяем сразу несколько элементов\n", "s[['c', 'd']] = 0\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Объекты типа `Series` можно сравнивать между собой и со скалярами. Сравнения, как и другие бинарные операции, выполняются для каждого элемента отдельно. Результатом становится новый объект, у которого в i-ой позиции стоит `True`, если сравнение соответствующего элемента дало истину:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 True\n", "1 False\n", "2 True\n", "dtype: bool \n", "\n", "0 False\n", "1 False\n", "2 True\n", "dtype: bool\n" ] } ], "source": [ "s1 = pd.Series([10, 5, 7])\n", "s2 = pd.Series([1, 12, 3])\n", "\n", "print(s1 > s2, '\\n')\n", "print(s2 == 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "С помощью массива, состоящего из булевых элементов, можно отфильтровать элементы другого массива той же размерности. При этом в результирующий объект `Series` попадают только элементы, для которых в соответствующей позиции фильтрующего массива находится `True`:" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 10\n", "2 7\n", "dtype: int64\n" ] } ], "source": [ "print(s1[s1 > s2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В заключение скажем, что объекты класса `Series` являются итерируемыми, т.е. могут использоваться в цикле `for ... in`:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.1\n", "0.2\n", "0.3\n" ] } ], "source": [ "s = pd.Series({'aaa':0.1, 'bbb':0.2, 'ccc':0.3})\n", "\n", "for item in s:\n", " print(item)" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "aaa\n", "bbb\n", "ccc\n" ] } ], "source": [ "# так выполняется итерация по меткам:\n", "for item in s.index:\n", " print(item)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Класс DataFrame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Класс `DataFrame` представляет двумерный изменяемый массив (матрицу), столбцами которого являются одномерные массивы `Series`. С помощью атрибутов `index` и `columns` задаются метки для строк и столбцов. Как и для типа `Series`, объекты `DataFrame` можно создавать несколькими способами:" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " col1 col2\n", "row1 1.0 0.1\n", "row2 2.0 0.2\n", "row3 3.0 NaN\n", "row5 NaN 0.3\n", "row6 NaN 0.4\n", "Index(['row1', 'row2', 'row3', 'row5', 'row6'], dtype='object')\n", "Index(['col1', 'col2'], dtype='object')\n" ] } ], "source": [ "# из словаря Series (ключи словаря становятся метками столбцов,\n", "# индексы Series объединяются и образуют индекс для строк)\n", "df = pd.DataFrame({'col1': pd.Series([1, 2, 3], ['row1', 'row2', 'row3']),\n", " 'col2': pd.Series([0.1, 0.2, 0.3, 0.4], ['row1', 'row2', 'row5', 'row6'])})\n", "print(df)\n", "print(df.index)\n", "print(df.columns)" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2\n", "r1 1 4\n", "r2 2 5\n", "r3 3 6\n" ] } ], "source": [ "# из словаря ndarray/list (ключи словаря становятся метками\n", "# столбцов, для строк используется индекс по умолчанию)\n", "df = pd.DataFrame({'c1': [1, 2, 3], 'c2':[4, 5, 6]})\n", "df.index = ['r1', 'r2', 'r3']\n", "print(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Семантически объект `DataFrame` может рассматриваться как [словарь](09_Collections.ipynb#Словарь), ключом в котором являются метки столбцов, а значением - соответствующие объекты `Series`. Операции, которые мы рассматривали для словаря, схожим образом выполняются и для объектов `DataFrame`: " ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2 c3\n", "r1 0.308978 0.940771 0.988228\n", "r2 0.778484 0.472404 NaN\n", "r3 0.570186 0.831688 0.568123\n", "r4 NaN 0.513793 0.575264\n" ] } ], "source": [ "df = pd.DataFrame({'c1': pd.Series(np.random.random(3), ['r1', 'r2', 'r3']),\n", " 'c2': pd.Series(np.random.random(4), ['r1', 'r2', 'r3', 'r4']),\n", " 'c3': pd.Series(np.random.random(3), ['r1', 'r3', 'r4'])})\n", "print(df)" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.30897794183961025 \n", "\n", "r1 0.988228\n", "r2 NaN\n", "Name: c3, dtype: float64 \n", "\n", "r1 0.940771\n", "r2 0.472404\n", "r3 0.831688\n", "r4 0.513793\n", "Name: c2, dtype: float64\n" ] } ], "source": [ "# получение конкретного элемента\n", "print(df['c1']['r1'], '\\n')\n", "\n", "# получение нескольких элементов столбца\n", "print(df['c3'][['r1', 'r2']], '\\n')\n", "\n", "# получение столбца целиком\n", "print(df['c2'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Очень удобной является возможность обращаться к столбцам и строкам как к атрибутам. Например, вот так мы можем переписать предыдущий блок кода:" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.30897794183961025 \n", "\n", "r1 0.988228\n", "r2 NaN\n", "Name: c3, dtype: float64 \n", "\n", "r1 0.940771\n", "r2 0.472404\n", "r3 0.831688\n", "r4 0.513793\n", "Name: c2, dtype: float64\n" ] } ], "source": [ "print(df.c1.r1, '\\n')\n", "print(df.c3[['r1', 'r2']], '\\n')\n", "print(df.c2)" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2 c3 c4\n", "r1 0.308978 0.940771 0.988228 NaN\n", "r2 0.778484 0.472404 NaN 0.461306\n", "r3 0.570186 0.831688 0.568123 NaN\n", "r4 NaN 0.513793 0.575264 0.369241 \n", "\n", " c1 c2 c3\n", "r1 0.308978 0.940771 0.988228\n", "r2 0.778484 0.472404 NaN\n", "r3 0.570186 0.831688 0.568123\n", "r4 NaN 0.513793 0.575264\n" ] } ], "source": [ "# добавление и удаление столбца\n", "df['c4'] = pd.Series(np.random.random(2), index=['r2', 'r4'])\n", "print(df, '\\n')\n", "\n", "del df['c4']\n", "print(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Существуют также удобные способы для обращения к строкам. В результате возвращаются объекты `Series`, индекс которых состоит из меток столобцов объекта `DataFrame`." ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "c1 0.778484\n", "c2 0.472404\n", "c3 NaN\n", "Name: r2, dtype: float64 \n", "\n", "c1 0.778484\n", "c2 0.472404\n", "c3 NaN\n", "Name: r2, dtype: float64\n" ] } ], "source": [ "# получаем строку по метке и по позиции\n", "print(df.loc['r2'], '\\n')\n", "print(df.iloc[1])" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2 c3\n", "r1 0.308978 0.940771 0.988228\n", "r3 0.570186 0.831688 0.568123 \n", "\n", " c1 c2\n", "r2 0.778484 0.472404\n", "r3 0.570186 0.831688\n" ] } ], "source": [ "# получаем сразу несколько строк\n", "print(df.loc[['r1', 'r3']], '\\n')\n", "\n", "# получаем несколько строк и несколько столбцов\n", "print(df.loc[['r2', 'r3'], ['c1', 'c2']])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Наконец, можно получить целый набор строк объекта `DataFrame` одним из следующих способов (в результате получается новый объект `DataFrame`, как и следовало ожидать):" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " c1 c2 c3\n", "r4 NaN 0.513793 0.575264\n", "r3 0.570186 0.831688 0.568123\n" ] } ], "source": [ "# используем операцию взятия среза\n", "df2 = df[3:1:-1]\n", "print(type(df2))\n", "print(df2)" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2 c3\n", "r1 0.308978 0.940771 0.988228\n", "r2 0.778484 0.472404 NaN\n" ] } ], "source": [ "# используем специфическую для массивов pandas операцию\n", "print(df.loc[['r1', 'r2']])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "С таблицами, можно выполнять арифметические операции, которые реализованы по тому же принципу, что и для объектов `Series`:" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2\n", "r1 0 3\n", "r2 1 4\n", "r3 2 5 \n", "\n", " c1 c2 c3\n", "r1 0.0 0.3 0.6\n", "r2 0.1 0.4 0.7\n", "r3 0.2 NaN NaN\n", "r4 NaN 0.5 0.8 \n", "\n", "c1 1.0\n", "c2 1.0\n", "c3 1.0\n", "dtype: float64\n" ] } ], "source": [ "df1 = pd.DataFrame({'c1': pd.Series([0, 1, 2], ['r1', 'r2', 'r3']),\n", " 'c2': pd.Series([3, 4, 5], ['r1', 'r2', 'r3'])})\n", "df2 = pd.DataFrame({'c1': pd.Series([0.0, 0.1, 0.2], ['r1', 'r2', 'r3']),\n", " 'c2': pd.Series([0.3, 0.4, 0.5], ['r1', 'r2', 'r4']),\n", " 'c3': pd.Series([0.6, 0.7, 0.8], ['r1', 'r2', 'r4'])})\n", "s = pd.Series(np.ones((3)), index=['c1', 'c2', 'c3'])\n", "\n", "print(df1, '\\n')\n", "print(df2, '\\n')\n", "print(s)" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2\n", "r1 1 4\n", "r2 2 5\n", "r3 3 6\n" ] } ], "source": [ "# арифметическая операция со скаляром\n", "print(df1 + 1)" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2 c3\n", "r1 0.0 0.9 NaN\n", "r2 0.1 1.6 NaN\n", "r3 0.4 NaN NaN\n", "r4 NaN NaN NaN\n" ] } ], "source": [ "# арифметическая операция с двумя матрицами (результат состоит\n", "# из объединения строк и столбцов операндов, значение Nan вставляется\n", "# в позиции, где отсутствует элемент в одном из операндов)\n", "print(df1 * df2)" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2 c3\n", "r1 -1.0 -0.7 -0.4\n", "r2 -0.9 -0.6 -0.3\n", "r3 -0.8 NaN NaN\n", "r4 NaN -0.5 -0.2\n" ] } ], "source": [ "# арифметическая операция с объектом Series (выполняется по строкам,\n", "# т.е. в индексе объекта Series должны быть указаны метки столбцов,\n", "# для которых нужно применить операцию)\n", "print(df2 - s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Покажем, как можно создать новый объект `DataFrame`, применив фильтрацию к элементам существующего:" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2 c3\n", "r2 0.1 0.4 0.7\n", "r4 NaN 0.5 0.8\n" ] } ], "source": [ "result = df2[df2.c2 > 0.3]\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В заключение скажем, что объекты `DataFrame` являются итерируемыми, и их можно использовать в циклах `for ... in`. При этом стоит отметить, что итерация по массивам pandas выполняется **медленно**, и лучше ее избегать (например, подобрав нужную функцию, которая сделает все сама)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Статистика" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В pandas существует большое количество функций и методов, предназначенных для получения различных статистических данных об одномерных и двумерных массивах. В этом разделе мы рассмотрим некоторые из них." ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 0.802763\n", "1 0.881109\n", "2 0.604589\n", "3 0.606030\n", "4 0.453705\n", "dtype: float64 \n", "\n", " c1 c2\n", "r1 0.679956 0.461280\n", "r2 0.697153 0.006743\n", "r3 0.152008 0.663765\n" ] } ], "source": [ "s = pd.Series(np.random.random(5))\n", "df = pd.DataFrame({'c1': pd.Series(np.random.random(3), index=['r1', 'r2', 'r3']),\n", " 'c2': pd.Series(np.random.random(3), index=['r1', 'r2', 'r3'])})\n", "\n", "print(s, '\\n')\n", "print(df)" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "sum=3.3481964332404925, prod=0.11758321064167483\n", "mean=0.6696392866480985, var=0.02933662862069077, std=0.1712793876118512\n" ] } ], "source": [ "# статистика для Series\n", "print('sum={}, prod={}'.format(\\\n", " s.sum(), s.prod()))\n", "print('mean={}, var={}, std={}'.format(\\\n", " s.mean(), s.var(), s.std()))" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "c1 1.529117\n", "c2 1.131789\n", "dtype: float64 \n", "\n", "r1 1.141236\n", "r2 0.703896\n", "r3 0.815773\n", "dtype: float64\n" ] } ], "source": [ "# статистика для DataFrame (методы все те же)\n", " \n", " # сумма элементов по столбцам\n", "print(df.sum(), '\\n')\n", "\n", " # сумма элементов по строкам\n", "print(df.sum(1))" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " c1 c2\n", "count 3.000000 3.000000\n", "mean 0.509706 0.377263\n", "std 0.309894 0.336472\n", "min 0.152008 0.006743\n", "25% 0.415982 0.234012\n", "50% 0.679956 0.461280\n", "75% 0.688554 0.562523\n", "max 0.697153 0.663765\n" ] } ], "source": [ "# основная статистика для DataFrame (для Series тот же метод)\n", "print(df.describe())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "На этом мы заканчиваем рассмотрение библиотеки pandas. Конечно, это лишь малая часть ее возможностей, однако, имея представление о работе с главными типами данных `Series` и `DataFrame`, можно легко продолжать самостоятельное изучение." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "- - -\n", "[Предыдущая: Стандартная библиотека](10_Standard_Library.ipynb) |\n", "[Содержание](00_Overview.ipynb#Содержание)" ] } ], "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.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }