Cognitive_technologies/лр1-2/.ipynb_checkpoints/8_numpy-checkpoint.ipynb

1966 lines
48 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"\n",
"## Библиотеки Python для анализа данных и машинного обучения\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Основы работы с библиотекой `numpy`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Знакомство с массивами"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сегодня мы познакомимся с библиотекой `numpy` (сокращение от *numeric Python*), которая часто используется в задачах, связанных с машинным обучением и построением статистических моделей.\n",
"\n",
"Массивы `numpy` очень похожи на списки (даже больше на вложенные списки), только они имеют одну особенность: элементы массива должны быть одного типа. Либо все элементы целые числа, либо числа с плавающей точкой, либо строки. Для обычных списков это условие не является обязательным:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 2, 4, 0]\n",
"[[1, 0, 3], [3, 6, 7], []]\n",
"[[1, 3, 6], ['a', 'b', 'c']]\n"
]
}
],
"source": [
"L = [1, 2, 4, 0]\n",
"E = [[1, 0, 3], [3, 6, 7], []]\n",
"D = [[1, 3, 6], ['a', 'b', 'c']]\n",
"\n",
"# все работает\n",
"print(L)\n",
"print(E)\n",
"print(D)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Чем хороши массивы `numpy`? Почему обычных списков недостаточно? Во-первых, обработка массивов занимает меньше времени (а их хранение меньше памяти), что очень актуально в случае работы с большими объемами данных. Во-вторых, функции `numpy` являются векторизованными их можно применять сразу ко всему массиву, то есть поэлементно. В этом смысле работа с массивами напоминает работу с векторами в R. Если в R у нас есть вектор `c(1, 2, 5)`, то, прогнав строчку кода `c(1, 2, 5)**2`, мы получим вектор, состоящий из квадратов значений: `c(1, 4, 25)`. Со списками в Python такое проделать не получится: понадобятся циклы или списковые включения. Зато с массивами `numpy` легко, и без всяких циклов! И в этом мы сегодня убедимся."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Для начала импортируем библиотеку (и сократим название до `np`):"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Получить массив `numpy` можно из обычного списка, просто используя функцию `array()`:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1, 2, 4, 0])"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = np.array(L)\n",
"A"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1, 2, 4, 0])"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A = np.array([1, 2, 4, 0]) \n",
"A"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Как видно из примера выше, список значений можно просто вписать в `array()`. Главное не забыть квадратные скобки: Python не сможет склеить перечень элементов в список самостоятельно и выдаст ошибку:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "only 2 non-keyword arguments accepted",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-5-83a5f8fa93ae>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mA\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mValueError\u001b[0m: only 2 non-keyword arguments accepted"
]
}
],
"source": [
"A = np.array(1, 2, 4, 0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Посмотрим, какую информацию о массиве можно получить. Например, тип его элементов:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"dtype('int64')"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.dtype # integer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Число измерений число \"маленьких\" массивов внутри \"большого\" массива (здесь такой один)."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.ndim"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\"Форма\" массива, о котором можно думать как о размерности матрицы кортеж, включающий число строк и столбцов. Здесь у нас всего одна строка, поэтому `numpy` считает только число элементов внутри массива."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(4,)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Так как массив `A` одномерный, обращаться к его элементам можно так же, как и к элементам списка, указывая индекс элемента в квадратных скобках:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Попытка использовать двойной индекс приведет к неудаче:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"ename": "IndexError",
"evalue": "invalid index to scalar variable.",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-10-ac48a874bd97>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mA\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;31m# index error\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mIndexError\u001b[0m: invalid index to scalar variable."
]
}
],
"source": [
"A[0][0] # index error"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Общее число элементов в массиве можно получить с помощью метода `size` (аналог `len()` для списков):"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.size"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Кроме того, по массиву можно получить разные описательные статистики:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.max() # максимум"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.min() # минимум"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.75"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.mean() # среднее"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"О других полезных методах можно узнать, нажав *Tab* после `np.`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Наконец, массив `numpy` можно легко превратить в список:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, 4, 0]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A.tolist()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"А теперь перейдем к многомерным массивам."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Многомерные массивы"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Создадим многомерный массив, взяв за основу вложенный список:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"S = np.array([[8, 1, 2], [2, 8, 9]])"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[8, 1, 2],\n",
" [2, 8, 9]])"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Посмотрим на число измерений:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S.ndim # два массива внутри"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(2, 3)"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S.shape # две строки (два списка) и три столбца (по три элемента в списке)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Общее число элементов в массиве (его длина):"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S.size"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Когда в массиве больше одного измерения, при различных операциях нужно указывать, по какому измерению мы движемся (по строкам или по столбцам). Посмотрим еще раз на массив S и подумаем о нем как о матрице, как о таблице с числами:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[8, 1, 2],\n",
" [2, 8, 9]])"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Можно найти максимальное значение по строкам или столбцам S:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([8, 8, 9])"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S.max(axis=0) # по столбцам - три столбца и три максимальных значения"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([8, 9])"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S.max(axis=1) # по строкам - две строки и два максимальных значения"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([5. , 4.5, 5.5])"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S.mean(axis=0)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([3.66666667, 6.33333333])"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S.mean(axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Для того, чтобы обратиться к элементу двумерного массива, нужно указывать два индекса: сначала индекс массива, в котором находится нужный нам элемент, а затем индекс элемента внутри этого массива:"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"8"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S[0][0]"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"9"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S[1][2]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Если мы оставим один индекс, мы просто получим массив с соответствующим индексом:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([8, 1, 2])"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Массивы изменяемые объекты в Python. Обращаясь к элементу массива, ему можно присвоить новое значение:"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[8, 1, 2],\n",
" [2, 8, 6]])"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S[1][2] = 6\n",
"S"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Чтобы выбрать сразу несколько элементов, как и в случае со списками, можно использовать срезы. Рассмотрим массив побольше."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"T = np.array([[1, 3, 7], [8, 10, 1], [2, 8, 9], [1, 0, 5]])"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 1, 3, 7],\n",
" [ 8, 10, 1],\n",
" [ 2, 8, 9],\n",
" [ 1, 0, 5]])"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Как и при выборе среза из списка, правый конец не включается:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 1, 3, 7],\n",
" [ 8, 10, 1]])"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"T[0:2] # массивы с индексами 0 и 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Можно сделать что-то еще более интересное выставить шаг среза. Другими словами, сообщить Python, что нужно брать? например, элементы, начиная с нулевого, с шагом 2: элемент с индексом 0, с индексом 2, с индексом 4, и так до конца массива."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1, 3, 7],\n",
" [2, 8, 9]])"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"T[0::2] # старт, двоеточие, двоеточие, шаг"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В примере выше совершенно логично были выбраны элементы с индексами 0 и 2."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Как создать массив?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Способ 1**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"С первым способом мы уже отчасти познакомились: можно получить массив из готового списка, воспользовавшись функцие `array()`:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([10.5, 45. , 2.4])"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.array([10.5, 45, 2.4])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Кроме того, при создании массива из списка можно изменить его форму, используя функцию `reshape()`."
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[2, 5, 6],\n",
" [9, 8, 0]])"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"old = np.array([[2, 5, 6], [9, 8, 0]])\n",
"old "
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(2, 3)"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"old.shape # 2 на 3"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[2, 5],\n",
" [6, 9],\n",
" [8, 0]])"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"new = old.reshape(3, 2) # изменим на 3 на 2\n",
"new"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(3, 2)"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"new.shape # 3 на 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Конечно, такие преобразования разумно применять, если произведение чисел в `reshape()` совпадает с общим числом элементов в массиве. В нашем случае в массиве `old` 6 элементов, поэтому из него можно получить массивы 2 на 3, 3 на 2, 1 на 6, 6 на 1. Несоответствующее число измерений приведет к ошибке:"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "cannot reshape array of size 6 into shape (2,4)",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-39-a803468708c0>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mold\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreshape\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# и Python явно пишет, что не так\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mValueError\u001b[0m: cannot reshape array of size 6 into shape (2,4)"
]
}
],
"source": [
"old.reshape(2, 4) # и Python явно пишет, что не так"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Способ 2**\n",
"\n",
"Можно создать массив на основе промежутка, созданного с помощью`arange()` функции из `numpy`, похожей на `range()`, только более гибкую. Посмотрим, как работает эта функция."
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([2, 3, 4, 5, 6, 7, 8])"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.arange(2, 9) # по умолчанию - как обычный range()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"По умолчанию эта функция создает массив, элементы которого начинаются со значения 2 и заканчиваются на значении 8 (правый конец промежутка не включается), следуя друг за другом с шагом 1. Но этот шаг можно менять:"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([2, 5, 8])"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.arange(2, 9, 3) # с шагом 3"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"И даже делать дробным!"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. , 6.5, 7. , 7.5, 8. ,\n",
" 8.5])"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.arange(2, 9, 0.5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"А теперь совместим `arange()` и `reshape()`, чтобы создать массив нужного вида:"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ],\n",
" [5.5, 6. , 6.5, 7. , 7.5, 8. , 8.5]])"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.arange(2, 9, 0.5).reshape(2, 7)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Получилось!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Способ 3**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Еще массив можно создать совсем с нуля. Единственное, что нужно четко представлять это его размерность, его форму, то есть опять же, число строк и столбцов. Библиотека `numpy` позволяет создать массивы, состоящие из нулей или единиц, а также \"пустые\" массивы (на самом деле, не совсем пустые, как убедимся позже). Удобство заключается в том, что сначала можно создать массив, инициализировать его (например, заполнить нулями), а затем заменить нули на другие значения в соответствии с требуемыми условиями. Как мы помним, массивы изменяемые объекты, и использовать замену в цикле еще никто не запрещал.\n",
"\n",
"Так выглядит массив из нулей:"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0., 0., 0.],\n",
" [0., 0., 0.],\n",
" [0., 0., 0.]])"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Z = np.zeros((3, 3)) # размеры в виде кортежа - не теряйте еще одни круглые скобки\n",
"Z"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"А так массив из единиц:"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1., 1.],\n",
" [1., 1.],\n",
" [1., 1.],\n",
" [1., 1.]])"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"O = np.ones((4, 2))\n",
"O"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"С пустым (*empty*) массивом все более загадочно:"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[6.92198590e-310, 6.92198590e-310],\n",
" [5.31021756e-317, 6.92194731e-310],\n",
" [5.39590831e-317, 5.39790038e-317]])"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Emp = np.empty((3, 2))\n",
"Emp"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Массив *Emp* не совсем пустой, в нем содержатся какие-то (псевдо)случайные элементы, которые примерно равны 0. Теоретически создавать массив таким образом можно, но не рекомендуется: лучше создать массив из \"чистых\" нулей, чем из какого-то непонятного \"мусора\"."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Задание:** Дан массив `ages` (см. ниже). Напишите программу с циклом, которая позволит получить массив `ages_bin` такой же размерности, что и `ages`, состоящий из 0 и 1 (0 - младше 18, 1 - не младше 18).\n",
"\n",
"*Подсказка:* используйте вложенный цикл."
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"ages = np.array([[12, 16, 17, 18, 14], [20, 22, 18, 17, 23], [32, 16, 44, 16, 23]])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*Решение:*"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0., 0., 0., 1., 0.],\n",
" [1., 1., 1., 0., 1.],\n",
" [1., 0., 1., 0., 1.]])"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"shape = ages.shape\n",
"ages_bin = np.zeros(shape)\n",
"ages_bin\n",
"\n",
"for i in range(0, shape[0]):\n",
" for j in range(0, shape[1]):\n",
" if ages[i][j] >= 18:\n",
" ages_bin[i][j] = 1\n",
"ages_bin"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Почему массивы `numpy` это удобно? "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Как уже было отмечено в начале занятия, операции с массивами можно производить поэлементно, не используя циклы или их аналоги. Посмотрим на массив `A`:"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1, 2, 4, 0])"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"А теперь возведем все его элементы в квадрат:"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 1, 4, 16, 0])"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A ** 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Или вычтем из всех элементов единицу:"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 0, 1, 3, -1])"
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"A - 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Кроме того, так же просто к элементам массива можно применять свои функции. Напишем функцию, которая будет добавлять к элементу 1, а затем считать от него натуральный логарифм (здесь эта функция актуальна, так как в массиве `A` есть 0)."
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
"def my_log(x):\n",
" return np.log(x + 1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Применим:"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.69314718, 1.09861229, 1.60943791, 0. ])"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"my_log(A)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"И никаких циклов и иных нагромождений."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Превратить многомерный массив в одномерный (как список) можно, воспользовавшись методами `flatten()` и `ravel()`."
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([12, 16, 17, 18, 14, 20, 22, 18, 17, 23, 32, 16, 44, 16, 23])"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ages.flatten() # \"плоский\" массив"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([12, 16, 17, 18, 14, 20, 22, 18, 17, 23, 32, 16, 44, 16, 23])"
]
},
"execution_count": 56,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ages.ravel()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Чем еще хорош `numpy`?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1.Позволяет производить вычисления нет необходимости дополнительно загружать модуль `math`."
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.0986122886681098"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.log(3) # натуральный логарифм"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2.6457513110645907"
]
},
"execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.sqrt(7) # квадратный корень"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"7.38905609893065"
]
},
"execution_count": 59,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.exp(2) # e^2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"2.Позволяет производить операции с векторами и матрицами. Пусть у нас есть два вектора `a` и `b`. "
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [],
"source": [
"a = np.array([1, 2, 3])\n",
"b = np.array([0, 4, 7])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Если мы просто умножим `a` на `b` с помощью символа `*`, мы получим массив, содержащий произведения соответствующих элементов `a` и `b`:"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 0, 8, 21])"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a * b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"А если мы воспользуемся функцией `dot()`, получится [скалярное произведение](https://ru.wikipedia.org/wiki/%D0%A1%D0%BA%D0%B0%D0%BB%D1%8F%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5) векторов (*dot product*)."
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"29"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.dot(a, b) # результат - число"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"При желании можно получить [векторное произведение](https://ru.wikipedia.org/wiki/%D0%92%D0%B5%D0%BA%D1%82%D0%BE%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5) (*cross product*): "
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([ 2, -7, 4])"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.cross(a, b) # результат- вектор"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Теперь создадим матрицу и поработаем с ней. Создадим ее не самым интуитивным образов из строки (да, так тоже можно)."
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [],
"source": [
"m = np.array(np.mat('2 4; 1 6')) # np.mat - матрица из строки, np.array - массив из матрицы "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Самое простоеи понятное, что можно сделать с матрицей транспонировать ее, то есть поменять местами строки и столбцы:"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[2, 1],\n",
" [4, 6]])"
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m.T "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Можно вывести ее диагональные элементы:"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([2, 6])"
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m.diagonal()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"И посчитать след матрицы сумму ее диагональных элементов:"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"8"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m.trace()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Задание.** Создайте [единичную матрицу](https://ru.wikipedia.org/wiki/%D0%95%D0%B4%D0%B8%D0%BD%D0%B8%D1%87%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B0) 3 на 3, создав массив из нулей, а затем заполнив ее диагональные элементы значениями 1.\n",
"\n",
"*Подсказка:* функция `fill_diagonal()`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*Решение:*"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1., 0., 0.],\n",
" [0., 1., 0.],\n",
" [0., 0., 1.]])"
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"I = np.zeros((3, 3))\n",
"np.fill_diagonal(I, 1)\n",
"I"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Правда, для создания массива в виде единичной матрицы в `numpy` уже есть готовая функция (наряду с `zeros` и `ones`):"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[1., 0., 0.],\n",
" [0., 1., 0.],\n",
" [0., 0., 1.]])"
]
},
"execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.eye(3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Найдем [обратную матрицу](https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D1%82%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B0):"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[-3, -5],\n",
" [-2, -7]])"
]
},
"execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.invert(m)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Для других операций с матрицами (и вычислений в рамках линейной алгебры) можно использовать функции из подмодуля `linalg`. Например, так можно найти определитель матрицы:"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"7.999999999999998"
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.linalg.det(m) # вспоминаем истории про числа с плавающей точкой, это 8 на самом деле"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"И собственные значения:"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1.17157288, 6.82842712])"
]
},
"execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.linalg.eigvals(m)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Полный список функций с описанием см. в [документации](https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.linalg.html)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"3.Библиотеку `numpy` часто используют с библиотекой для визуализации `matplotlib`. \n",
"\n",
"Рассмотрим функцию `linspace()` в следующей лекции по визуализации с `matplotlib`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"4.Еще `numpy` можно использовать в статистике. Но поговорим об этом позже, когда подойдем к блоку, посвященному теории вероятностей и статистике."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}