4451 lines
128 KiB
Plaintext
4451 lines
128 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<!-- dom:TITLE: Основы NumPy: массивы и векторные вычисления -->\n",
|
||
"# Основы NumPy: массивы и векторные вычисления\n",
|
||
"<!-- dom:AUTHOR: С.В. Лемешевский Email:sergey.lemeshevsky@gmail.com at Институт математики НАН Беларуси -->\n",
|
||
"<!-- Author: --> \n",
|
||
"**С.В. Лемешевский** (email: `sergey.lemeshevsky@gmail.com`), Институт математики НАН Беларуси\n",
|
||
"\n",
|
||
"Date: **Mar 18, 2020**\n",
|
||
"\n",
|
||
"<!-- Common Mako variable and functions -->\n",
|
||
"<!-- -*- coding: utf-8 -*- -->\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Рассматривается библиотека NumPy. NumPy (сокращение от *Numerical\n",
|
||
"Python*) предоставляет эффективный интерфейс для хранения и работы с\n",
|
||
"данными. В какой-то степени массивы NumPy аналогичны спискам Python,\n",
|
||
"но массивы NumPy обеспечивают гораздо более эффективное хранение и\n",
|
||
"операции с данными при увеличении массивов в размере. Если NumPy\n",
|
||
"установлен его можно импортировать следующей командой:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"import numpy"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Большинство людей в мире научного Python импортируют NumPy, используя\n",
|
||
"`np` в качестве псевдонима:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"import numpy as np"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"> **О встроенной документации.**\n",
|
||
">\n",
|
||
"> Как было рассказано выше IPython дает возможность быстро просмотреть\n",
|
||
"> содержание пакета, а также документацию по функциям.\n",
|
||
"> \n",
|
||
"> Например, для того чтобы отобразить содержание пространства имен\n",
|
||
"> `numpy`, можно выполнить следующее:\n",
|
||
">"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"> \n",
|
||
"> Для отображения встроенной документации NumPy можно набрать\n",
|
||
"> следующее:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np?"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"> Более детальную документацию вместе с учебниками и другими ресурсами\n",
|
||
"> можно найти по адресу: <https://numpy.org/>\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"Одна из причин того, почему NumPy настолько важен для численных\n",
|
||
"расчетов в Python, заключается в том, что он разработан, как уже\n",
|
||
"упоминалось выше, для более эффективной работы с большими массивами\n",
|
||
"данных, а именно:\n",
|
||
"\n",
|
||
"* NumPy хранит данные в непрерывных блоках памяти, независимо от других встроенных объектов Python. Библиотека алгоритмов NumPy, написанная на языке C, может работать на этой памяти без проверки типов или других накладных расходов. Массивы NumPy также используют намного меньше памяти, чем встроенные объекты Python.\n",
|
||
"\n",
|
||
"* Операции NumPy выполняют сложные вычисления над всем массивом без использования цикла `for`.\n",
|
||
"\n",
|
||
"Для того чтобы показать разницу в производительности, рассмотрим\n",
|
||
"массив NumPy из одного миллиона целых чисел и эквивалентный список:"
|
||
]
|
||
},
|
||
{
|
||
"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": [
|
||
"my_arr = np.arange(1000000)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"my_list = list(range(1000000))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%time for _ in range(10): my_arr2 = my_arr*2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%time for _ in range(10): my_list2 = [x * 2 for x in my_list]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Объект многомерных массивов `ndarray`\n",
|
||
"<div id=\"numpy:ndarray\"></div>\n",
|
||
"\n",
|
||
"Одной из ключевых особенностей NumPy является объект N-мерных\n",
|
||
"массивов, или `ndarray`, который является быстрым, гибким контейнером \n",
|
||
"для больших наборов данных в Python. Массивы позволяют выполнять\n",
|
||
"математические операции над целыми блоками данных, используя схожий\n",
|
||
"синтаксис для эквивалентных операций со скалярными элементами.\n",
|
||
"\n",
|
||
"Рассмотрим пример: создадим небольшой массив случайных данных:"
|
||
]
|
||
},
|
||
{
|
||
"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.random.randn(2, 3)"
|
||
]
|
||
},
|
||
{
|
||
"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": [
|
||
"data * 10"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data + data"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"`ndarray` является общим контейнером для однородных многомерных\n",
|
||
"данных, то есть все элементы должны быть одного типа. Каждый массив имеет\n",
|
||
"атрибут `shape` — кортеж, указывающий размер каждого измерения, и\n",
|
||
"атрибут `dtype`, объект, описывающий тип данных массива:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data.shape"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data.dtype"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Создание массива\n",
|
||
"<div id=\"numpy:ndarray:create\"></div>\n",
|
||
"\n",
|
||
"Простейший способ создания массива — использование функции\n",
|
||
"`array`. Она принимает некоторый объект типа последовательностей\n",
|
||
"(включая другие массивы) и создает новый массив NumPy, содержащий\n",
|
||
"переданные данные. Например:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data1 = [6, 7.5, 8, 0, 1]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr1 = np.array(data1)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"In [15]: arr1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Вложенные последовательности, как список списков одинаковой длины,\n",
|
||
"будут преобразованы в многомерный массив:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2 = np.array(data2)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Если явно не указано, `np.array` пытается вывести подходящий тип\n",
|
||
"данных для массива, который он создает. Тип данных хранится в\n",
|
||
"специальном объекте `dtype` метаданных; например, в двух предыдущих\n",
|
||
"примерах мы имеем:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"In [19]: arr1.dtype\n",
|
||
"In [20]: arr2.dtype"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Кроме `np.array` есть несколько других функций для создания новых\n",
|
||
"массивов:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.zeros(10)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.zeros((3, 6))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.empty((2, 3, 2))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.arange(15)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Таблица 1 : Функции создания массивов\n",
|
||
"\n",
|
||
"\n",
|
||
"<table border=\"1\">\n",
|
||
"<thead>\n",
|
||
"<tr><th align=\"left\"> Функция </th> <th align=\"left\"> Описание </th> </tr>\n",
|
||
"</thead>\n",
|
||
"<tbody>\n",
|
||
"<tr><td align=\"left\"> <code>array</code> </td> <td align=\"left\"> Преобразует входные данные (список, кортеж, массив или другая последовательность) в <code>ndarray</code>, либо прогнозируя <code>dtype</code>, либо используя заданный <code>dtype</code>; копирует данные по-умолчанию </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>asarray</code> </td> <td align=\"left\"> Преобразует входные данные в <code>ndarray</code>, но не копирует их, если аргумент уже типа <code>ndarray</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>arange</code> </td> <td align=\"left\"> Подобна встроенной функции <code>range</code>, но возвращает <code>ndarray</code> вместо списка </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>ones</code> </td> <td align=\"left\"> Создает массив из единиц заданной формы и <code>dtype</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>ones_like</code> </td> <td align=\"left\"> Получает на вход массив и создает массив из единиц с такими же формой и <code>dtype</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>zeros</code> и <code>zeros_like</code> </td> <td align=\"left\"> Подобны <code>ones</code> и <code>ones_like</code>, но создают массивы из нулей </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>empty</code> и <code>empty_like</code> </td> <td align=\"left\"> Создают новые массивы, выделяя новую память, но не инициализируют их какими-либо значениями, как <code>ones</code> и <code>zeros</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>full</code> </td> <td align=\"left\"> Создает массив заданных формы и <code>dtype</code>, при этом все элементы инициализируются заданным значением <code>fill_value</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>full_like</code> </td> <td align=\"left\"> Получает на вход массив и создает массив с такими же формой и <code>dtype</code> и значениями <code>fill_value</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>eye</code> и <code>identity</code> </td> <td align=\"left\"> Создает квадратную единичную матрицу (с единицами на диагонали и нулями вне нее) размера $N\\times N$ </td> </tr>\n",
|
||
"</tbody>\n",
|
||
"</table>"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Арифметические операции с массивами NumPy\n",
|
||
"<div id=\"numpy:ndarray:arithm\"></div>\n",
|
||
"\n",
|
||
"Массивы NumPy, как упоминалось выше, позволяют выполнять операции без\n",
|
||
"использования циклов. Любые арифметические операции между массивами\n",
|
||
"одинакового размера выполняются поэлементно:"
|
||
]
|
||
},
|
||
{
|
||
"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": [
|
||
"arr = np.array([[1., 2., 3.], [4., 5., 6.]])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"In [3]: arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr * arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr - arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Арифметические операции со скалярами распространяют скалярный аргумент\n",
|
||
"к каждому элементу массива:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"1 / arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr ** 0.5"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2 > arrщ"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Основы индексирования и срезы\n",
|
||
"<div id=\"numpy:ndarray:index\"></div>\n",
|
||
"\n",
|
||
"Существует много способов выбора подмножества данных или элементов\n",
|
||
"массива. Одномерные массивы — это просто, на первый взгляд они\n",
|
||
"аналогичны спискам Python:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.arange(10)"
|
||
]
|
||
},
|
||
{
|
||
"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[5]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr[5:8]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr[5:8] = 12"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Как видно, если присвоить скалярное значение срезу, как например,\n",
|
||
"`arr[5:8] = 12`, значение присваивается всем элементам среза. Первым\n",
|
||
"важным отличием от списков Python заключается в том, что срезы массива\n",
|
||
"являются *представлениями* исходного массива. Это означает, что данные\n",
|
||
"не копируются и любые изменения в представлении будут отражены в\n",
|
||
"исходном массиве.\n",
|
||
"\n",
|
||
"Рассмотрим пример. Сначала создадим срез массива `arr`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr_slice = arr[5:8]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr_slice"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Теперь, если мы изменим значения в массиве `arr_slice`, то они\n",
|
||
"отразятся в исходном массиве `arr`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr_slice[1] = 12345"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"«Голый» срез `[:]` присвоит все значения в массиве:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr_slice[:] = 64"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Поскольку NumPy был разработан для работы с очень большими массивами,\n",
|
||
"вы можете представить себе проблемы с производительностью и памятью,\n",
|
||
"если NumPy будет настаивать на постоянном копировании данных. \n",
|
||
"\n",
|
||
"> **Замечание.**\n",
|
||
">\n",
|
||
"> Если вы захотите скопировать срез в массив вместо отображения, нужно\n",
|
||
"> явно скопировать массив, например, `arr[5:8].copy()`.\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"С массивами более высокой размерности существует больше вариантов. В\n",
|
||
"двумерных массивах каждый элемент это уже не скаляр, а одномерный\n",
|
||
"массив."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2d[2]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Таким образом, к отдельному элементу можно получить доступ\n",
|
||
"рекурсивно, либо передать разделенный запятыми список\n",
|
||
"индексов. Например, следующие два примера эквивалентны:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2d[2]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2d[0][2]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Если в многомерном массиве опустить последние индексы, то возвращаемый\n",
|
||
"объект будет массивом меньшей размерности. Например, создадим массив\n",
|
||
"размерности $2 \\times 2 \\times 3$:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr3d"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"При этом `arr3d[0]` — массив размерности $2 \\times 3$:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr3d[0]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Можно присваивать `arr3d[0]` как скаляр, так и массивы:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"old_values = arr3d[0].copy()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr3d[0] = 42"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr3d"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr3d[0] = old_values"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr3d"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Аналогично, `arr3d[1, 0]` возвращает все значения, чьи индексы\n",
|
||
"начинаются с `(1, 0)`, формируя одномерный массив:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr3d[1, 0]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Это выражение такое же, как если бы мы проиндексировали в два этапа:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"x = arr3d[1]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"x"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"x[0]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Индексирование с помощью срезов\n",
|
||
"\n",
|
||
"<div id=\"numpy:ndarray:index:slices\"></div>\n",
|
||
"\n",
|
||
"Как одномерные объекты, такие как списки, можно получать срезы\n",
|
||
"массивов посредством знакомого синтаксиса:"
|
||
]
|
||
},
|
||
{
|
||
"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[1:6]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Рассмотрим введенный выше двумерный массив `arr2d`. Получение срезов\n",
|
||
"этого массива немного отличается от одномерного:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2d"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr[:2]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Как видно, мы получили срез вдоль оси 0, первой оси. Срез, таким\n",
|
||
"образом, выбирает диапазон элементов вдоль оси. Выражение `arr2d[:2]`\n",
|
||
"можно прочитать как «выбираем первые две строки массива `arr2d`».\n",
|
||
"\n",
|
||
"Можно передавать несколько срезов:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2d[:2, 1:]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"При получении срезов мы получаем только отображения массивов того же\n",
|
||
"числа размерностей. Используя целые индексы и срезы, можно получить\n",
|
||
"срезы меньшей размерности:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2d[1, :2]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr2d[:2, 2]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Смотрите рис. [Срезы двумерного массива](#numpy:ndarray:fig:1).\n",
|
||
"\n",
|
||
"<!-- dom:FIGURE: [fig-numpy/numpy-1.png, width=800 frac=1.0] Срезы двумерного массива <div id=\"numpy:ndarray:fig:1\"></div> -->\n",
|
||
"<!-- begin figure -->\n",
|
||
"<div id=\"numpy:ndarray:fig:1\"></div>\n",
|
||
"\n",
|
||
"<!-- end figure -->"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Логическое (Boolean) индексирование\n",
|
||
"<div id=\"numpy:ndarray:index:boolean\"></div>\n",
|
||
"\n",
|
||
"Рассмотрим следующий пример: пусть есть массив с данными (случайными)\n",
|
||
"и массив, содержащий имена с повторениями:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data = np.random.randn(7, 4)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"names"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Предположим, что каждое имя соответствует строке в массиве `data`, и\n",
|
||
"мы хотим выбрать все строки с соответствующим именем `'Bob'`. Как и\n",
|
||
"арифметические операции, операции сравнения (такие как `==`) с\n",
|
||
"массивами также векторизованы. Таким образом, сравнение массива\n",
|
||
"`names` со строкой `'Bob'` возвращает булев массив:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"names == 'Bob'"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Этот булев массив может использоваться при индексировании массива:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data[names == 'Bob']"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Булев массив должен быть той же длины, что и ось массива, по которой\n",
|
||
"осуществляется индексация. Вы даже можете смешивать и сопоставлять\n",
|
||
"логические массивы со срезами или целыми числами (или\n",
|
||
"последовательностями целых чисел)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data[names == 'Bob', 2:]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data[names == 'Bob', 3]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Чтобы выбрать все, кроме `'Bob'`, можно использовать `!=` или\n",
|
||
"обращение условия ` `:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"names != 'Bob'"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data[~(names == 'Bob')]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Оператор ` ` может быть полезен при инвертировании общего условия:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"cond = names == 'Bob'"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Выбрав два из трех имен для объединения нескольких логических условий,\n",
|
||
"можно использовать логические арифметические операторы, такие как `&` (и) и `|`\n",
|
||
"(или):"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"mask = (names == 'Bob') | (names == 'Will')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"mask"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data[mask]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Выбор данных из массива с помощью логического индексирования *всегда*\n",
|
||
"создает копию данных, даже если возвращаемый массив не изменяется. \n",
|
||
"\n",
|
||
"> **Предупреждение.**\n",
|
||
">\n",
|
||
"> Ключевые слова Python `and` и `or` не работают с булевыми массивами.\n",
|
||
"> Используйте `&` (и) и `|` (или).\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"Присвоение значений массивам работает обычным образом. Замену\n",
|
||
"всех отрицательных значений на `0` можно сделать следующим образом:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data[data < 0] = 0"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Можно также легко присваивать значения целым строкам или столбцам:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"data[names != 'Joe'] = 7"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Необычное индексирование\n",
|
||
"<div id=\"numpy:ndarray:fancy\"></div>\n",
|
||
"\n",
|
||
"*Необычное индексирование* (*fancy indexing*) — это термин, принятый в\n",
|
||
"NumPy для описания индексации с использованием целочисленных\n",
|
||
"массивов.\n",
|
||
"\n",
|
||
"Предположим, у нас есть массив размера $8 \\times 4$"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.empty((8, 4))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"for i in range(8):\n",
|
||
" arr[i] = i"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Чтобы выбрать подмножество строк в определенном порядке, можно\n",
|
||
"просто передать список или массив целых чисел, указывающих желаемый\n",
|
||
"порядок:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr[[4, 3, 0, 6]]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Использование отрицательных индексов выделяет строки с конца:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr[[-3, -5, -7]]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Передача нескольких индексных массивов делает кое-что другое:\n",
|
||
"выбирается одномерный массив элементов, соответствующий каждому\n",
|
||
"кортежу индексов:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.arange(32).reshape((8, 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[[1, 5, 7, 2], [0, 3, 1, 2]]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Здесь выбраны элементы с индексами `(1, 0)`, `(5, 3)`, `(7, 1)` и\n",
|
||
"`(2, 2)`. Независимо от того какая размерность у массива (в нашем\n",
|
||
"случае двумерный массив), результат такого индексирования — всегда\n",
|
||
"одномерный массив.\n",
|
||
"\n",
|
||
"Поведение индексирования в этом случае немного отличается\n",
|
||
"от того, что могли ожидать некоторые пользователи, а именно:\n",
|
||
"пользователь мог ожидать прямоугольную область, сформированную путем\n",
|
||
"выбора поднабора строк и столбцов матрицы. Ниже представлен один из\n",
|
||
"способов получения таких массивов с помощью необычного индексирования:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Имейте в виду, что необычное индексирование, в отличие от среза,\n",
|
||
"всегда копирует данные в новый массив. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Транспонирование массивов и замена осей\n",
|
||
"<div id=\"numpy:ndarray:transp\"></div>\n",
|
||
"\n",
|
||
"*Транспонирование* — это особый способ изменения формы массива, который\n",
|
||
"возвращает представление исходных данных без их копирования. Массивы\n",
|
||
"имеют метод `transpose`, а также специальный атрибут `T`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.arange(15).reshape((3, 5))"
|
||
]
|
||
},
|
||
{
|
||
"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.T"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"При выполнении матричных вычислений эта процедура может выполняться\n",
|
||
"очень часто, например, при вычислении произведения матриц с помощью\n",
|
||
"функции `np.dot`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.random.randn(6, 3)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Для массивов большей размерности метод `transpose` принимает кортеж с\n",
|
||
"номерами осей, задающий перестановку осей:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.arange(16).reshape((2, 2, 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.transpose((1, 0, 2))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Здесь оси были переупорядочены следующим образом: вторая ось стала\n",
|
||
"первой, первая ось — второй, а последняя осталась без изменений.\n",
|
||
"\n",
|
||
"Простое транспонирование с помощью `.T` является частным случаем\n",
|
||
"замены осей. Массивы имеют метод `swapaxes`, который получает пару\n",
|
||
"номеров осей и переставляет указанные оси."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr.swapaxes(1, 2)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Метод `swapaxes` возвращает представление данных без копирования."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- doconce-section-nickname: \"ndarray\" -->\n",
|
||
"<!-- End: -->\n",
|
||
"\n",
|
||
"# Универсальные функции: быстрые поэлементные функции от массивов\n",
|
||
"<div id=\"numpy:ufuncs\"></div>\n",
|
||
"\n",
|
||
"\n",
|
||
"*Универсальные функции* (или *ufunc*) — это функции, которые выполняют\n",
|
||
"поэлементные операции над данными массива. Можно рассматривать их как\n",
|
||
"быстрые векторизованные обертки для простых функций, которые\n",
|
||
"принимают одно или несколько скалярных значений и дают один или\n",
|
||
"несколько скалярных результатов.\n",
|
||
"\n",
|
||
"Многие универсальные функции — это простые поэлементные\n",
|
||
"преобразования, такие как `sqrt` и `exp`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.arange(10)"
|
||
]
|
||
},
|
||
{
|
||
"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": [
|
||
"np.sqrt(arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.exp(arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Они являются *унарными* универсальными функциями. Такие функции как\n",
|
||
"`add` или `maximum` принимают два массива (таким образом,\n",
|
||
"они *бинарные*) и возвращают один массив:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"x = np.random.randn(8)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"y = np.random.randn(8)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"x"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"y"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.maximum(x, y)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Функция `np.maximum` вычисляет максимумы элементов массивов `x` и `y`.\n",
|
||
"\n",
|
||
"Универсальная функция может возвращать несколько массивов (хотя и не\n",
|
||
"часто). Например, функция `np.modf` (векторизованная версия встроенной\n",
|
||
"функции `divmod`) возвращает целую и дробную части массива чисел с\n",
|
||
"плавающей запятой:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.random.randn(7) * 5"
|
||
]
|
||
},
|
||
{
|
||
"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": [
|
||
"frac_part, int_part = np.modf(arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"frac_part"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"int_part"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Универсальные функции принимают опциональный аргумент `out`, который\n",
|
||
"позволяет выполнять операции прямо в заданном массиве."
|
||
]
|
||
},
|
||
{
|
||
"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": [
|
||
"np.sqrt(arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.sqrt(arr, arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"В таблицах [2](#numpy:ufuncs:tbl:1) и [3](#numpy:ufuncs:tbl:2)\n",
|
||
"представлены доступные универсальные функции."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Таблица 2 : Унарные универсальные функции <div id=\"numpy:ufuncs:tbl:1\"></div>\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"<table border=\"1\">\n",
|
||
"<thead>\n",
|
||
"<tr><th align=\"center\"> Функция </th> <th align=\"center\"> Описание </th> </tr>\n",
|
||
"</thead>\n",
|
||
"<tbody>\n",
|
||
"<tr><td align=\"left\"> <code>abs</code>, <code>fabs</code> </td> <td align=\"left\"> Вычисляет абсолютные значения каждого элементов массива </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>sqrt</code> </td> <td align=\"left\"> Вычисляет квадратный корень из каждого элемента массива (эквивалентно <code>arr ** 0.5</code>) </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>square</code> </td> <td align=\"left\"> Вычисляет квадрат каждого элемента массива (эквивалентно <code>arr ** 2</code>) </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>exp</code> </td> <td align=\"left\"> Вычисляет экспоненту ($e^x$) от каждого элемента массива </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>log</code>, <code>log10</code>, <code>log2</code>, <code>log1p</code> </td> <td align=\"left\"> Вычисляет натуральный, десятичный логарифмы, логарифм по основанию $2$ и $\\log(1 + x)$, соответственно </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>sign</code> </td> <td align=\"left\"> Вычисляет знак каждого элемента: $1$ (положительный элемент), $0$ (ноль), $-1$ (отрицательный элемент) </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>ceil</code> </td> <td align=\"left\"> Вычисляет наименьшее целое число большее либо равное каждого элемента массива </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>floor</code> </td> <td align=\"left\"> Вычисляет наибольшее целое число меньшее либо равное каждого элемента массива </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>rint</code> </td> <td align=\"left\"> Округляет элементы к ближайшим целым сохраняя <code>dtype</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>modf</code> </td> <td align=\"left\"> Возвращает дробные и целые части каждого элемента массива </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>isnan</code> </td> <td align=\"left\"> Возвращает булев массив, указывающий является каждый элемент входного массива <code>NaN</code> (Not A Number) </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>isfinite</code>, <code>isinf</code> </td> <td align=\"left\"> Возвращает булев массив, указывающий является каждый элемент конечным (не <code>inf</code> и не <code>NaN</code>) или бесконечным, соотвественно </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>cos</code>, <code>cosh</code>, <code>sin</code>, <code>sinh</code>, <code>tan</code>, <code>tanh</code> </td> <td align=\"left\"> Обычные и тригонометрические функции </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>arccos</code>, <code>arccosh</code>, <code>arcsin</code>, <code>arcsinh</code>, <code>arctan</code>, <code>arctanh</code> </td> <td align=\"left\"> Обратные тригонометрические функции </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>logical_not</code> </td> <td align=\"left\"> Вычисляет истиное значение <code>not x</code> для каждого элемента (эквивалентно <code> arr</code>) </td> </tr>\n",
|
||
"</tbody>\n",
|
||
"</table>"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Таблица 3 : Бинарные универсальные функции <div id=\"numpy:ufuncs:tbl:2\"></div>\n",
|
||
"\n",
|
||
"\n",
|
||
"<table border=\"1\">\n",
|
||
"<thead>\n",
|
||
"<tr><th align=\"left\"> Функция </th> <th align=\"left\"> Описание </th> </tr>\n",
|
||
"</thead>\n",
|
||
"<tbody>\n",
|
||
"<tr><td align=\"left\"> <code>add</code> </td> <td align=\"left\"> Складывает соответствующие элементы массивов </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>subtract</code> </td> <td align=\"left\"> Вычитает соответствующие элементы второго массива из элементов первого </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>multiply</code> </td> <td align=\"left\"> Перемножает элементы массивов </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>divide</code>, <code>floor_devide</code> </td> <td align=\"left\"> Деление или деление с отбрасыванием остатка </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>power</code> </td> <td align=\"left\"> Возведение элементов первого массива в степени указанные во втором массиве </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>maximum</code>, <code>fmax</code> </td> <td align=\"left\"> Поэлементный максимум, <code>fmax</code> игнорирует <code>NaN</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>minimum</code>, <code>fmin</code> </td> <td align=\"left\"> Поэлементный минимум, <code>fmin</code> игнорирует <code>NaN</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>mod</code> </td> <td align=\"left\"> Поэлементный модуль (остаток от деления) </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>copysign</code> </td> <td align=\"left\"> Копирует знаки элементов второго массива в элементы первого массива </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>greater</code>, <code>greater_equal</code>, <code>less</code>, <code>less_equal</code>, <code>equal</code>, <code>not_equal</code> </td> <td align=\"left\"> Поэлементное сравнение (эквивалентны операторам <code>></code>, <code>>=</code>, <code><</code>, <code><=</code> <code>==</code>, <code>!=</code>) </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>logical_and</code>, <code>logical_or</code>, <code>logical_xor</code> </td> <td align=\"left\"> Вычисляет поэлементное значение истинности логической операций (эквивалентны операторам <code>&</code>, <code> | </code>, <code>^</code>) </td> </tr>\n",
|
||
"</tbody>\n",
|
||
"</table>\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- doconce-section-nickname: \"ufuncs\" -->\n",
|
||
"<!-- End: -->"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Программирование с использованием массивов\n",
|
||
"<div id=\"numpy:prog-with-array\"></div>\n",
|
||
"\n",
|
||
"Использование массивов NumPy позволяет выражать многие виды задач\n",
|
||
"обработки данных в виде кратких выражений с массивами, которые в\n",
|
||
"противном случае потребовали использования циклов. Такая практика\n",
|
||
"замены явных циклов на выражения с массивами обычно\n",
|
||
"называется *векторизацией*. Вообще говоря, векторизованные операции \n",
|
||
"с массивами часто на один-два (или более) порядка быстрее, чем их\n",
|
||
"эквиваленты Python, что оказывает большое влияние на любые виды\n",
|
||
"вычислений.\n",
|
||
"\n",
|
||
"В качестве простого примера, предположим, что мы хотим вычислить\n",
|
||
"функцию `sqrt(x^2 + y^2)` по всей регулярной сетке значений. Функция\n",
|
||
"`np.meshgrid` получает два одномерных массива и возвращает две\n",
|
||
"двумерные матрицы соответствующие всем парам `(x, y)` в двух массивах:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"points = np.arange(-5, 5, 0.01)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"xs, ys = np.meshgrid(points, points)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"xs"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"ys"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Теперь для вычисления значений на всей сетке нужно написать то же\n",
|
||
"выражение, которое было бы написано для двух координат:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"z = np.sqrt(xs ** 2 + ys ** 2)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"z"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Теперь воспользуемся библиотекой `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": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"plt.title('Визуализация функции $\\sqrt{x^2 + y^2}$ на сетке')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Результат представлен на рисунке\n",
|
||
"[Визуализация функции, вычисленной на сетке](#numpy:prog-with-array:fig:2). Здесь использовалась функция\n",
|
||
"`imshow` библиотеки `matplotlib` для создания изображения по\n",
|
||
"двумерному массиву значений сеточной функции.\n",
|
||
"\n",
|
||
"<!-- dom:FIGURE: [fig-numpy/numpy-2.png, width=800 frac=1.0] Визуализация функции, вычисленной на сетке <div id=\"numpy:prog-with-array:fig:2\"></div> -->\n",
|
||
"<!-- begin figure -->\n",
|
||
"<div id=\"numpy:prog-with-array:fig:2\"></div>\n",
|
||
"\n",
|
||
"<!-- end figure -->\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Выражение условной логики в операциях с массивами\n",
|
||
"<div id=\"numpy:prog-with-array:cond\"></div>\n",
|
||
"\n",
|
||
"Функция `np.where` — векторизованная версия тернарного выражения\n",
|
||
"`x if condition else y`. Предположим, у нас есть булев массив и два\n",
|
||
"массива значений:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"cond = np.array([True, False, True, True, False])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Предположим, мы хотим выбрать из массива `xarr` значения в том случае,\n",
|
||
"когда значение элемента массива `cond` равно `True`, иначе выбираем\n",
|
||
"значение из массива `yarr`. С использованием списка это может выглядеть\n",
|
||
"следующим образом:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"result = [(x if c else y) for x, y, c in zip(xarr, yarr, cond)]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"result"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Такой подход имеет несколько проблем. Во-первых, это не будет быстро\n",
|
||
"работать для очень больших массивов (потому что вся работа будет\n",
|
||
"выполняться интерпретируемым Python-кодом). Во-вторых, это не будет\n",
|
||
"работать с многомерными массивами. С помощью `np.where` все это можно\n",
|
||
"записать коротко:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"result = np.where(cond, xarr, yarr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"result = np.where(cond, xarr, yarr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Второй и третий аргументы функции `np.where` не обязательно должны\n",
|
||
"быть массивами, они могут быть скалярами. Типичное использование\n",
|
||
"функции `np.where` в анализе данных — это создание нового массива\n",
|
||
"значений на основе другого массива. Предположим есть матрица случайно\n",
|
||
"сгенерированных значений и нужно заменить все положительные значения\n",
|
||
"на число $2$, а отрицательные значения — на $-2$. Это легко сделать с\n",
|
||
"помощью функции `np.where`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.random.randn(4, 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": [
|
||
"np.where(arr > 0, 2, -2)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Можно объединять скаляры и массивы при использовании\n",
|
||
"`np.where`. Например, заменим все положительные элементы массива на\n",
|
||
"$2$:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.where(arr > 0, 2, arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Математические и статистические методы\n",
|
||
"<div id=\"numpy:prog-with-array:math-stat\"></div>\n",
|
||
"\n",
|
||
"Некоторые математические функции, которые вычисляют статистику по\n",
|
||
"данным всего массива или по данным по какой-либо оси, доступны как\n",
|
||
"методы класса. Вы можете использовать *агрегаты* (часто называемые\n",
|
||
"*редукциями*), такие как `sum`, `mean` и `std` (стандартное отклонение),\n",
|
||
"либо вызывая метод экземпляра массива, либо используя функцию NumPy\n",
|
||
"верхнего уровня.\n",
|
||
"\n",
|
||
"Ниже сгененированы случайные нормально распределенные данные и\n",
|
||
"вычислены некоторые статистические свойства:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.random.randn(5, 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.mean()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.mean(arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr.sum()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Функции типа `mean` и `sum` принимают опциональный аргумент `axis`,\n",
|
||
"указывающий по какой оси вычислять статистику. В результате получается\n",
|
||
"массив на одну размерность меньше."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr.mean(axis=1)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr.sum(axis=0)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Здесь `arr.mean(axis=1)` означает «вычислить средние значения по\n",
|
||
"столбцам», а `arr.sum(axis=0)` означает «вычислить сумму по строкам».\n",
|
||
"\n",
|
||
"Другие методы, такие как `cumsum` и `cumprod`, не агрегируют, а\n",
|
||
"создают массив промежуточных результатов:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr.cumsum()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"В многомерных массивах В многомерных массивах функции накопления,\n",
|
||
"такие как cumsum, возвращают массив того же размера, но с частичными\n",
|
||
"агрегатами, вычисленными вдоль указанной оси в соответствии с каждым\n",
|
||
"срезом меньшего размера:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])"
|
||
]
|
||
},
|
||
{
|
||
"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.cumsum(axis=0)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr.cumprod(axis=1)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"В таблице [4](#numpy:prog-with-array:tbl:1) представлен полный список таких функций."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Таблица 4 : Основные статистические методы для массивов <div id=\"numpy:prog-with-array:tbl:1\"></div>\n",
|
||
"\n",
|
||
"\n",
|
||
"<table border=\"1\">\n",
|
||
"<thead>\n",
|
||
"<tr><th align=\"left\"> Функция </th> <th align=\"left\"> Описание </th> </tr>\n",
|
||
"</thead>\n",
|
||
"<tbody>\n",
|
||
"<tr><td align=\"left\"> <code>sum</code> </td> <td align=\"left\"> Сумма всех элементов массива или вдоль оси. Массив нулевой длины имеет сумму, равную 0 </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>mean</code> </td> <td align=\"left\"> Арифметическое среднее. Массив нулевой длины имеет среднее значение <code>NaN</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>std</code>, <code>var</code> </td> <td align=\"left\"> Стандартное отклонение и дисперсия, соответственно, с возможностью задания степени свободы (по умолчанию знаменатель равен <code>n</code>) </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>min</code>, <code>max</code> </td> <td align=\"left\"> Минимум и максимум </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>argmin</code>, <code>argmax</code> </td> <td align=\"left\"> Индексы минимального и максимального элементов, соответственно </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>cumsum</code> </td> <td align=\"left\"> Накопленная сумма элементов, начиная с $0$ </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>cumprod</code> </td> <td align=\"left\"> Накопленное произведение элементов, начиная с $1$ </td> </tr>\n",
|
||
"</tbody>\n",
|
||
"</table>"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Методы для булевых массивов\n",
|
||
"<div id=\"numpy:prog-with-array:bool\"></div>\n",
|
||
"\n",
|
||
"В рассмотренных выше методах булевы значения приводятся к $1$ (`True`)\n",
|
||
"и $0$ (`False`). Таким образом, `sum` часто используется как средство\n",
|
||
"подсчета значений `True` в логическом массиве:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.random.randn(100)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"(arr > 0).sum()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Есть два дополнительных метода: `any` и `all`, которые очень полезны\n",
|
||
"при работе с булевыми массивами. Метод `any` проверяет, есть ли хотя\n",
|
||
"бы одно значение в массиве равное `True`, a `all` проверяет, все ли\n",
|
||
"значения в массиве равны `True`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.array([False, False, True, False])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr.any()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr.all()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Эти методы также работают с небулевыми массивами. В этом случае\n",
|
||
"ненулевые элементы оцениваются как `True`. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Сортировка\n",
|
||
"<div id=\"numpy:prog-with-array:sorting\"></div>\n",
|
||
"\n",
|
||
"Как и встроенный тип `list` массивы NumPy могут быть отсортированы с\n",
|
||
"помощью метода `sort`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.random.randn(6)"
|
||
]
|
||
},
|
||
{
|
||
"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.sort()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Можно отсортировать каждый одномерный массив многомерного вдоль оси,\n",
|
||
"которая задается как аргумент метода `sort`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.random.randn(5, 3)"
|
||
]
|
||
},
|
||
{
|
||
"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.sort(1)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Метод верхнего уровня `np.sort` возвращает отсортированный массив\n",
|
||
"вместо изменения исходного массива. Быстрый и простой способ вычислить\n",
|
||
"квантили массива — это отсортировать его и выбрать значение в\n",
|
||
"определенном ранге:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"large_arr = np.random.randn(1000)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"large_arr.sort()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"large_arr[int(0.05 * len(large_arr))] # 5% квантиль"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Основные операции над множествами для массивов\n",
|
||
"<div id=\"numpy:prog-with-array:unique\"></div>\n",
|
||
"\n",
|
||
"В NumPy имеются некоторые основные операции над множествами для\n",
|
||
"одномерных массивов. Обычно используется функция `np.unique`, которая\n",
|
||
"возвращает отсортированные уникальные значения в массиве:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.unique(names)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.unique(ints)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Сравните `np.unique` с альтернативой на чистом Python:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"sorted(set(names))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Другая функция, `np.in1d`, проверяет нахождение значений из одного массива в\n",
|
||
"другом, возвращая логический массив:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"values = np.array([6, 0, 0, 3, 2, 5, 6])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.in1d(values, [2, 3, 6])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Таблица 5 : Операции над множествами из массивов <div id=\"numpy:prog-with-array:tbl:2\"></div>\n",
|
||
"\n",
|
||
"\n",
|
||
"<table border=\"1\">\n",
|
||
"<thead>\n",
|
||
"<tr><th align=\"left\"> Метод </th> <th align=\"left\"> Описание </th> </tr>\n",
|
||
"</thead>\n",
|
||
"<tbody>\n",
|
||
"<tr><td align=\"left\"> <code>unique(x)</code> </td> <td align=\"left\"> Возвращает отсортированные единственные элементы из <code>x</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>intersect1d(x, y)</code> </td> <td align=\"left\"> Возвращает отсортированные общие элементы массивов <code>x</code> и <code>y</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>union1d(x, y)</code> </td> <td align=\"left\"> Возвращает отсортированное объединение элементов массивов <code>x</code> и <code>y</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>in1d(x, y)</code> </td> <td align=\"left\"> Возвращает булев массив, указывающий содержится ли каждый элемент массива <code>x</code> в <code>y</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>setdiff1d(x, y)</code> </td> <td align=\"left\"> Разность множеств: элементы массива <code>x</code>, которых нет в <code>y</code> </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>setxor1d(x, y)</code> </td> <td align=\"left\"> Симметричная разность: элементы, которые есть либо в <code>x</code>, либо в <code>y</code>, но не в обоих массивах </td> </tr>\n",
|
||
"</tbody>\n",
|
||
"</table>\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- doconce-section-nickname: \"prog-with-array\" -->\n",
|
||
"<!-- End: -->"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Чтение и запись в/из файлы массивов\n",
|
||
"<div id=\"numpy:input-output\"></div>\n",
|
||
"\n",
|
||
"NumPy позволяет сохранять на диск и загружать с диска в текстовые или\n",
|
||
"двоичные файлы. Здесь рассмотрим только встроенные двоичные файлы\n",
|
||
"NumPy, так как большинство предпочтут использовать `pandas` или другие\n",
|
||
"инструменты для загрузки текста или таблиц.\n",
|
||
"\n",
|
||
"Функции `np.save` и `np.load` — это две рабочие лошадки для\n",
|
||
"эффективного сохранения и загрузки данных массива на диск. Массивы\n",
|
||
"сохраняются по умолчанию в несжатый двоичный формате с расширением\n",
|
||
"файла `.npy`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arr = np.arange(10)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.save('some_array', arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"В пути к файлу не указывается разширение, оно добавляется по\n",
|
||
"умолчанию. Массив с диска потом можно загрузить с помощью функции\n",
|
||
"`np.load`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.load('some_array.npy')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Можно сохранить несколько массивов в один несжатый файл, используя\n",
|
||
"функцию `np.savez` и передавая массивы в качестве аргументов:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.savez('array_archive.npz', a=arr, b=arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"При загрузке файла `.npz` возвращается объект типа словаря, который\n",
|
||
"содержит отдельные массивы:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arch = np.load('array_archive.npz')"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"arch['b']"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Если данные хорошо сжимаются, можно использовать функцию\n",
|
||
"`np.savez_compressed`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.savez_compressed('arrays_compressed.npz', a=arr, b=arr)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- doconce-section-nickname: \"input-output\" -->\n",
|
||
"<!-- End: -->\n",
|
||
"\n",
|
||
"# Линейная алгебра\n",
|
||
"<div id=\"numpy:linear-alg\"></div>\n",
|
||
"\n",
|
||
"Матричные вычисления, такие как умножение матриц, построение\n",
|
||
"разложений матриц, вычисление определителя и др. являются важной\n",
|
||
"частью любой библиотеки программ для численных расчетов. В отличие от\n",
|
||
"некоторых языков программирования, таких как MATLAB, в NumPy операция\n",
|
||
"`*` — это поэлементное умножение матриц, а не стандартное умножение\n",
|
||
"матриц из линейной алгебры. В связи с этим в NumPy для умножения\n",
|
||
"матриц реализована функция `dot` как в виде метода объекта типа\n",
|
||
"`ndarray`, так и в виде функции из пространства имен `numpy`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.array([[1., 2., 3.], [4., 5., 6.]])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"y = np.array([[6., 23.], [-1, 7], [8, 9]])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"x"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"y"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"x.dot(y)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Выражение `x.dot(y)` эквивалентно `np.dot(x, y)`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.dot(x, y)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Произведение матрицы на согласованный одномерный массив дает\n",
|
||
"одномерный массив:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.dot(x, np.ones(3))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Операция `@` также выполняет умножение матриц:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"x @ np.ones(3)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Модуль `numpy.linalg` стандартный набор функций для разложения матриц, а\n",
|
||
"также вычисления определителя и обратной матрицы. Они реализуются с\n",
|
||
"помощью тех же стандартных библиотек линейной алгебры, которые\n",
|
||
"используются в других языках (например, MATLAB и R), таких как BLAS,\n",
|
||
"LAPACK, или, возможно (в зависимости от вашей сборки NumPy),\n",
|
||
"проприетарной Intel MKL (Math Kernel Library):"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"from numpy.linalg import inv, qr"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"X = np.random.randn(5, 5)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"mat = X.T.dot(X)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"inv(mat)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"mat.dot(inv(mat))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"q, r = qr(mat)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"r"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"В таблице 6 представлены наиболее часто используемые функции линейной\n",
|
||
"алгебры."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Таблица 6 : Часто используемые функции модуля `numpy.linalg` <div id=\"numpy:linear-alg:tbl:1\"></div>\n",
|
||
"\n",
|
||
"\n",
|
||
"<table border=\"1\">\n",
|
||
"<thead>\n",
|
||
"<tr><th align=\"left\">Функция</th> <th align=\"left\"> Описание </th> </tr>\n",
|
||
"</thead>\n",
|
||
"<tbody>\n",
|
||
"<tr><td align=\"left\"> <code>diag</code> </td> <td align=\"left\"> Возвращает диагональные элементы квадратной матрицы в виде одномерного массива или преобразует одномерный массив в квадратную матрицу с нулями вне диагонали </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>dot</code> </td> <td align=\"left\"> Умножение матриц </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>trace</code> </td> <td align=\"left\"> След матрицы — сумма диагональных элементов </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>det</code> </td> <td align=\"left\"> Определитель матрицы </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>eig</code> </td> <td align=\"left\"> Вычисляет собственные значения и собственные векторы квадратной матрицы </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>inv</code> </td> <td align=\"left\"> Вычисляет обратную матрицу </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>pinv</code> </td> <td align=\"left\"> Вычисляет псевдообратную матрицу Мура—Пенроуза </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>qr</code> </td> <td align=\"left\"> Вычисляет $QR$ разложение матрицы </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>svd</code> </td> <td align=\"left\"> Вычисляет сингулярное разложение матрицы (SVD) </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>solve</code> </td> <td align=\"left\"> Решает линейную систему $A x = b$, где $A$ — квадратная матрица </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>lstsq</code> </td> <td align=\"left\"> Находит решение линейной системы $Ax = b$ методом наименьших квадратов </td> </tr>\n",
|
||
"</tbody>\n",
|
||
"</table>\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- doconce-section-nickname: \"linear-alg\" -->\n",
|
||
"<!-- End: -->\n",
|
||
"\n",
|
||
"# Генерация псевдослучайных числел\n",
|
||
"<div id=\"numpy:pseudornd\"></div>\n",
|
||
"\n",
|
||
"Модуль `numpy.random` дополняет встроенный в Python модуль `random`\n",
|
||
"функциями для эффективной для эффективной генерации целых массивов\n",
|
||
"выборок, подчиненых многим видам вероятностных\n",
|
||
"распределений. Например, можно получить массив размера $4\\times 4$\n",
|
||
"выборок из нормального распределения, используя функцию `normal`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"samples = np.random.normal(size=(4, 4))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"samples"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Встроенный модуль `random` генерирует только одно число за раз. Как\n",
|
||
"видно из приведенного ниже теста, `numpy.random` на порядок быстрее\n",
|
||
"генерирует очень большие выборки:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"from random import normalvariate"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"N = 1000000"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%timeit samples = [normalvariate(0, 1) for _ in range(N)]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%timeit np.random.normal(size=N)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"163/5000\n",
|
||
"Мы говорим, что это *псевдослучайные* числа, потому что они генерируются\n",
|
||
"алгоритмом с детерминированным поведением на основе *начального*\n",
|
||
"(seed) числа генератора случайных чисел. Можно изменить начальное\n",
|
||
"число генератора случайных чисел, используя функцию `np.random.seed`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"np.random.seed(1234)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Функция, генерирующие данные, из `numpy.random` используют глобальное\n",
|
||
"начальное число. Чтобы избежать глобального состояния, вы можете\n",
|
||
"использовать `np.random.RandomState` для создания генератора\n",
|
||
"случайных чисел, изолированного от других:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"rng = np.random.RandomState(1234)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"rng.randn(10)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"В таблице [7](#numpy:pseudornd:tbl:1) представлены некоторые функции\n",
|
||
"модуля `numpy.random`."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Таблица 7 : Некоторые функции модуля `numpy.random` <div id=\"numpy:pseudornd:tbl:1\"></div>\n",
|
||
"\n",
|
||
"\n",
|
||
"<table border=\"1\">\n",
|
||
"<thead>\n",
|
||
"<tr><th align=\"left\"> Функция </th> <th align=\"left\"> Описание </th> </tr>\n",
|
||
"</thead>\n",
|
||
"<tbody>\n",
|
||
"<tr><td align=\"left\"> <code>seed</code> </td> <td align=\"left\"> Начальная точка генератора случайных чисел </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>permutation</code> </td> <td align=\"left\"> Возвращает случайную перестановку последовательности или возвращает переставленный диапазон </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>shuffle</code> </td> <td align=\"left\"> Произвольно переставляет последовательность </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>rand</code> </td> <td align=\"left\"> Генерирует выборку из равномерного распределения </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>randint</code> </td> <td align=\"left\"> Генерирует случайные целые числа из заданного интервала </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>randn</code> </td> <td align=\"left\"> Генерирует выборку из нормального распределения со средним значением $0$ и стандартным отклонением $1$ </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>binomial</code> </td> <td align=\"left\"> Генерирует выборку из биномиального распределения </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>normal</code> </td> <td align=\"left\"> Генерирует выборку из нормального (гауссового) распределения </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>beta</code> </td> <td align=\"left\"> Генерирует выборку из $\\beta$-распределения </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>chisquare</code> </td> <td align=\"left\"> Генерирует выборку из $\\chi^2$-распределения </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>gamma</code> </td> <td align=\"left\"> Генерирует выборку из $\\Gamma$-распределения </td> </tr>\n",
|
||
"<tr><td align=\"left\"> <code>uniform</code> </td> <td align=\"left\"> Генерирует выборку из равномерного распределения на $[0, 1)$ </td> </tr>\n",
|
||
"</tbody>\n",
|
||
"</table>\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- doconce-section-nickname: \"pseudornd\" -->\n",
|
||
"<!-- End: -->"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Пример: Случайное блуждание\n",
|
||
"<div id=\"numpy:example\"></div>\n",
|
||
"\n",
|
||
"Моделирование [случайного блуждания](https://ru.wikipedia.org/wiki/%D0%A1%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D0%BE%D0%B5_%D0%B1%D0%BB%D1%83%D0%B6%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5) \n",
|
||
"предоставляет иллюстрацию применения операций с массивами. Вначале\n",
|
||
"рассмотрим случайное блуждание, начинающееся с $0$ с шагами $1$ и\n",
|
||
"$-1$, происходящие с равной вероятностью.\n",
|
||
"\n",
|
||
"Ниже представлен код сценария на чистом Python, который реализует\n",
|
||
"простое случайное блуждание в 1000 шагов и использует модуль `random`:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"import random\n",
|
||
"\n",
|
||
"position = 0\n",
|
||
"walk = [position]\n",
|
||
"steps = 1000\n",
|
||
"for i in range(100):\n",
|
||
" step = 1 if random.randint(0, 1) else -1\n",
|
||
" position += step\n",
|
||
" walk.append(position)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"На рис. [numpy:example:fig:1](#numpy:example:fig:1) графически представлены 100 первых значений одного случайного\n",
|
||
"блуждания.\n",
|
||
"\n",
|
||
"<!-- dom:FIGURE: [fig-numpy/numpy-3.png, width=800 frac=1.0] Простое случайное блуждание <div id=\"numpy:example:fig:1\"></div> -->\n",
|
||
"<!-- begin figure -->\n",
|
||
"<div id=\"numpy:example:fig:1\"></div>\n",
|
||
"<!-- end figure -->\n",
|
||
"\n",
|
||
"\n",
|
||
"Заметим, что `walk` — это просто накопленная сумма случайных шагов, а\n",
|
||
"она может быть вычислена с помощью метода массива. Таким образом,\n",
|
||
"можно воспользоваться модулем `np.random` для генерации 1000 бросаний\n",
|
||
"монеты за раз, установить соответствующие значения в $1$ и $-1$ и\n",
|
||
"вычислить накопленную сумму:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"\n",
|
||
"nsteps = 1000\n",
|
||
"draws = np.random.randint(0, 2, size=nsteps)\n",
|
||
"steps = np.where(draws > 0, 1, -1)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Отсюда можно получить статистические данные, такие, например, как\n",
|
||
"минимум и максимум:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"walk.min()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"walk.max()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Более сложная статистика — *время первого «перехода»*, т.е. шаг, на\n",
|
||
"котором пусть достигает некоторого значения. Например, можно узнать,\n",
|
||
"сколько времени понадобилось случайному блужданию, чтобы пройти как\n",
|
||
"минимум 10 шагов от начала в любом направлении. Выражение\n",
|
||
"`np.abs(walk) >= 10` даст булев массив, указывающий, где элемент\n",
|
||
"`walk` достиг или превысил значение $10$. Но нам нужен индекс первого\n",
|
||
"элемента, равного $10$ или $-10$. Мы можем получить это с помощью\n",
|
||
"функции `argmax`, которая вернет первый индекс максимального\n",
|
||
"значения в булевом массиве (`True` — максимальное значение):"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"metadata": {
|
||
"collapsed": false,
|
||
"jupyter": {
|
||
"outputs_hidden": false
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"(np.abs(walk) >= 10).argmax()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Обратите внимание, что использование argmax здесь не всегда\n",
|
||
"эффективно, потому что оно всегда выполняет полное сканирование\n",
|
||
"массива. В этом особом случае, когда есть значение `True`, мы знаем,\n",
|
||
"что это максимальное значение.\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- doconce-section-nickname: \"example\" -->\n",
|
||
"<!-- End: -->"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Упражнения\n",
|
||
"<div id=\"numpy:exer\"></div>\n",
|
||
"\n",
|
||
"\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<!-- --- begin exercise --- -->\n",
|
||
"\n",
|
||
"## Матрица из нулей и единиц\n",
|
||
"<div id=\"numpy:exer:decor-matr\"></div>\n",
|
||
"\n",
|
||
"Напишите функцию `decorate_matrix`, которая получает на вход одно целое\n",
|
||
"число больше единицы. Функция должна возвращать матрицу $N\\times N$, у\n",
|
||
"которой на границах стоят единицы, а на всех остальных позициях(если\n",
|
||
"остались позиции не на границах) стоят нули.\n",
|
||
"\n",
|
||
"<!-- --- end exercise --- -->"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"<!-- --- begin exercise --- -->\n",
|
||
"\n",
|
||
"## Моделирование нескольких случайных блужданий за раз\n",
|
||
"<div id=\"numpy:exer:rnd-walk\"></div>\n",
|
||
"\n",
|
||
"Написать сценарий, в котором выполняется моделирование многих\n",
|
||
"случайных блужданий (путей) (например, 5000 путей). Кроме того,\n",
|
||
"вычислить максимальное и минимальное значения, полученные по всем\n",
|
||
"путям. Вычислить минимальное время перехода через $30$ или $-30$.\n",
|
||
"Используйте разные генераторы случайных чисел.\n",
|
||
"Имя файла: `many_random_walk_ans.py`.\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- doconce-section-nickname: \"exer\" -->\n",
|
||
"<!-- End: -->\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"<!-- Local Variables: -->\n",
|
||
"<!-- doconce-chapter-nickname: \"numpy\" -->\n",
|
||
"<!-- End: -->\n",
|
||
"<!-- --- end exercise --- -->"
|
||
]
|
||
}
|
||
],
|
||
"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
|
||
}
|