Numerical Python или NumPy - это библиотека языка программирования Python, которая поддерживает большие многомерные массивы и матрицы, и поставляется с обширной коллекцией высокоуровневых математических функций для работы с этими массивами.
Matrix-sig, специальная группа интересов, была основана в 1995 году с целью разработки пакета для расчетов с массивами, совместимого с языком программирования Python. В том же году Джим Хьюгунин разработал пакет Numeric для работы с матрицами. Позже, в 2005 году, Трэвис Олифант включил функции NumArray и C-API в код Numeric для создания NumPy (Numericical Python), который разрабатывался как часть проекта SciPy. Они были отделены друг от друга, чтобы избежать необходимости установки большого пакета SciPy просто, чтобы получить объект массив.
В оставшейся части этой статьи «>>>» представляет собой запрос интерпретатора Python; операторы без этой подсказки показывают вывод кода.
Установка
NumPy - это библиотека под лицензией BSD для языка программирования Python. Она поставляется с дистрибутивами Python, такими как Anaconda, Enthought Canopy и Pyzo. Ее также можно установить с помощью менеджеров пакетов, таких как dnf или pip. В системах на базе Ubuntu и Debian для установки NumPy введите:
$ sudo apt-get install python3-numpy
После установки NumPy нам нужно импортировать его, чтобы использовать предоставленные им функции:
import numpy as n
Вышеуказанная команда создаст псевдоним «n» при импорте пакета. После импорта пакета он будет активен до выхода из интерпретатора. Если программы сохраняются в файлах, вы должны импортировать NumPy в каждый файл.
NumPy, SciPy, Pandas и Scikit-learn
В Python много пакетов, поддерживающих научные приложений. NumPy, как и Matlab, используется для эффективных вычислений, связанных с массивами. Он также предоставляет векторизованные математические функции, такие как sin() и cos(). SciPy помогает нам в научных вычислениях, предоставляя методы интегрирования, интерполяции, обработки сигналов, статистики и линейной алгебры. Pandas помогает в анализе данных, статистике и визуализации. Мы используем Scikit-learn, когда хотим работать с алгоритмами машинного обучения. Кажется, что NumPy уступает всем этим пакетам. Но истина в том, что все эти пакеты используют NumPy для работы.
ndarray
Душа NumPy - это ndarray, n-мерный массив. Из приведенного ниже фрагмента кода вы можете видеть, что всякий раз, когда вы применяете функцию «type» в любом массиве NumPy, она возвращает тип numpy.ndarray независимо от типа данных, хранящихся в нем.
>>> import numpy as n
>>> a=n.array([1,2,3])
>>> type(a)
<type 'numpy.ndarray'>
>>> b=n.array(['a','b','c'])
>>> type(b)
<type 'numpy.ndarray'>
В отличие от структуры данных list в Python, ndarray содержит только элементы одного и того же типа данных. Ниже перечислены некоторые атрибуты объекта ndarray. Примеры, показанные с описанием каждого атрибута, относятся к массиву «a», определение которого таково:
>>>a=n.array([[1,2,3],[3,4,5]])
ndarray.ndim: отображает количество измерений массива. Массив «a» в примере является двумерным, и, следовательно, вывод выглядит следующим образом:
>>> a.ndim
2
ndarray.shape: отображает размеры массива, как показано ниже:
>>> a.shape
(2, 3)
ndarray.size: отображает общее количество элементов в массиве, как показано ниже:
>>> a.size
6
ndarray.dtype: отображает тип данных элементов в зависимости от типа хранимых в нем данных. Встроенные типы включают int, bool, float, complex, bytes, str, unicode, buffer; все остальные называются объектами. По умолчанию dtype ndarray - float64.
>>> a.dtype
dtype('int64')
В случае строк «type» будет отображаться как dtype(‘S#’), где # обозначает длину строки:
>>> c=n.array(['sarah','serin','jaden'])
>>> c.dtype
dtype('S5')
ndarray.itemsize: отображает размер каждого элемента в байтах. В примере «a» содержит целые числа, а размер целых чисел - 8 байтов. Следовательно, вывод выглядит следующим образом:
>>> a.itemsize
8
Создание ndarray
Мы уже видели в приведенных выше примерах, как ndarray создаются из списка Python с помощью array(). Вместо списка можно использовать кортеж. Можно явно указать тип данных элементов в массиве, как показано ниже:
>>> e=n.array([[1,2,3],[3,4,5]],dtype='S2')
>>> e
array([['1', '2', '3'],
['3', '4', '5']],
dtype='|S2')
>>> e.dtype
dtype('S2')
Существуют и другие способы генерации массивов. Некоторые из них перечислены ниже.
ones(shape[,dtype, order]): возвращает массив заданных размеров и типа, заполненный единицами. «Order» в наборе параметров указывает, следует ли хранить данные в строках или столбцах. Ниже приведен пример.
>>> a=n.ones(3,dtype='S1')
>>> a
array(['1', '1', '1'],
dtype='|S1')
Если указанным dtype является Sn, независимо от значения 'n', массив, сгенерированный ones(), будет содержать строку длины 1. Но в какой-то более поздний момент мы сможем заменить '1' на строку длиной до 'n'.
empty(shape[, dtype, order]): возвращает массив заданной размерности и типа без инициализации записей. В приведенном ниже сегменте кода указанный тип dtype равен «S1». Следовательно, массив «a» может быть использован позже для хранения строк длиной 1.
>>> a=n.empty(3,dtype='S1')
>>> a
array(['', '', ''],
dtype='|S1')
full(shape, fill_value[, dtype, order]): возвращает массив заданной размерности, заполненный 'fill_value'. Если dtype явно не указано, будет сформирован массив с числами с плавающей точкой с предупреждающим сообщением. Пример приведен ниже:
>>> a=n.full((3,3),2,dtype=int)
>>> a
array([[2, 2, 2],
[2, 2, 2],
[2, 2, 2]])
fromstring(string[, dtype, count, sep]): возвращает 1-мерный массив, инициализированный 'string'. NumPy принимает «count» элементов типа «dtype» из «string» и генерирует массив. «String» будет интерпретироваться как двоичный массив, если строка «sep» не задана, и как ASCII в противном случае. Я хотел бы добавить еще немного о fromstring(). Эта функция требует, чтобы размер входной строки был кратным размеру элемента. Если не указано, массив, созданный с использованием этой функции, будет иметь dtype 'float64', для которого требуется 8 байтов. Рассмотрим приведенный ниже пример:
>>> a=n.fromstring('123')
Traceback (most recent call last): File "<stdin>", line 1, in <module>
ValueError: string size must be a multiple of element size
Приведенный выше оператор должен сгенерировать массив из строки «123». Но он выдаст сообщение об ошибке, поскольку его длина не кратна 8.
>>> a=n.fromstring('12345678')
Вышеприведенный оператор успешно сгенерирует массив, как показано ниже:
>>> a
array([ 6.82132005e-38])
Рассмотрим пример:
>>>a=n.fromstring('123456',dtype='S2',count=2)
Здесь dtype указывается как «S2». Таким образом, массив «a» будет содержать элементы длины 2.
>>> aarray(['12', '34'], dtype='|S2')
Мы можем видеть, что «a» содержит только два элемента, поскольку число, указанное в fromstring(), равно 2.
loadtxt(fname[, dtype][, comments][, skiprows][, delimiter][, converters][, usecol] ... ..): возвращает массив, содержащий элементы, сформированные из данных в файле. Содержимое входного файла, например loadtxt.txt, приведено ниже:
abc def ghi
jkl mno pqr
Используем функцию loadtxt:
>>>n.loadtxt('/home/alex/loadtxt.txt',dtype='S3')
array([['abc', 'def', 'ghi'],
['jkl', 'mno', 'pqr']],
dtype='|S3')
Мы видим, что комментарий в выводе автоматически удален. Перед применением этой функции мы должны убедиться, что все строки в файле содержат равное количество строк. Мы можем указать в опции комментариев loadtxt() символ, который будет отмечать начало комментариев. По умолчанию это символ «#». Опция skiprows поможет пропустить первые «skiprows» строк во входном файле.
arange([start], stop[, step,][, dtype]): возвращает массив, содержащий элементы в пределах диапазона.
Имеется еще много функций, которые помогают в создании массивов. Они подробно описаны на официальном сайте scipy.org.
Функции, ассоциированные с массивами
Мы писали программы для поиска, сортировки элементов, поиска индекса ненулевых элементов, умножения двух матриц и т. д. Мы знаем, насколько объемны эти программы, если они написаны на C. Каждая из этих задач может быть решена с помощью всего одного оператора, использующего NumPy. Ниже приводится описание нескольких таких функций. Большинство функций, связанных с массивом, возвращают массив.
nonzero(a): возвращает кортеж, содержащий индексы ненулевых элементов массива.
>>> a=n.array([[0,0,2],[3,0,0],[0,0,0]])
>>> n.nonzero(a)
(array([0, 1]), array([2, 0]))
В определении «а» мы можем видеть, что индексы ненулевых элементов в нем равны [0,2] и [1,0]. Каждый элемент в выводе nonzero() представляет собой массив, содержащий позицию индекса ненулевого элемента в этой размерности. В этом случае первый массив содержит номера строк, а второй массив содержит номера столбцов ненулевых элементов. Если бы мы имели третье измерение во входном массиве, кортеж содержал бы еще один элемент, показывающий позиции ненулевых элементов в этом измерении.
>>> a[n.nonzero(a)]
array([2, 3])
Приведенный выше код показывает нам, как извлекать ненулевые элементы из массива.
transpose(a[, axes]): возвращает новый ndarray после выполнения перестановки в размерностях. В приведенном ниже фрагменте кода показан трехмерный массив и его транспонирование.
>>> a=n.array((((1,2,3),(4,5,6)),((7,8,9),(0,1,2))))
>>> a
array([[[1, 2, 3],
[4, 5, 6]],
[[7, 8, 9],
[0, 1, 2]]])
>>> n.transpose(a)
array([[[1, 7],
[4, 0]],
[[2, 8],
[5, 1]],
[[3, 9],
[6, 2]]])
sum(a[, axis][, dtype][, out][, keepdims]): возвращает сумму элементов вдоль данной оси. В списке опций есть ndarray, в который должен быть записан результат. keepdims - это логическое значение, которое, если установлено значение «True», будет удерживать axis, которая уменьшает размерность с размером 1 результате. Ниже приведен пример 3D-массива. В этом случае axis принимает значения от 0 до 2.
>>> a=n.array((((1,2,3),(4,5,6)),((7,8,9),(0,1,2))))
>>> a
array([[[1, 2, 3],
[4, 5, 6]],
[[7, 8, 9],
[0, 1, 2]]])
>>> n.sum(a,axis=0)
array([[ 8, 10, 12],
[ 4, 6, 8]])
>>> n.sum(a,axis=1)
array([[ 5, 7, 9],
[ 7, 9, 11]])
>>> n.sum(a,axis=2,keepdims=True)
array([[[ 6],
[15]],
[[24],
[ 3]]])
prod(a[, axis][, dtype][, out][, keepdims]): возвращает произведение элементов вдоль данной оси.
Имеются также функции argmax, min, argmin, ptp, clip, conj, round, trace, cumsum, mean, var, std, cumprod, которые упрощают научные вычисления. Имеются функции для преобразования массивов, манипуляций с формами, выбора элементов и так далее. Если вы хотите углубиться в них, посетите официальный сайт SciPy.
Операции с массивами
Арифметические операции: операторы типа «+», «-», «*», «/» и «%» могут применяться непосредственно к массивам NumPy. Следует отметить, что все операции являются элементарными операциями. Результат умножения 2D-массивов показан ниже:
>>> c=n.array([[1,2],[3,4]])
>>> d=n.array([[1,3],[2,1]])
>>> c*d
array([[1, 6],
[6, 4]])
Если вы хотите выполнить умножение матриц, используйте функцию dot(), как показано ниже, или создайте матрицы с помощью функции matrix, и используйте с ними оператор «*».
>>> c=n.array([[1,2],[3,4]])
>>> d=n.array([[1,3],[2,1]])
>>> c
array([[1, 2],
[3, 4]])
>>> d
array([[1, 3],
[2, 1]])
>>> n.dot(c,d)
array([[ 5, 5],
[11, 13]])
Операции отношения: NumPy позволяет сравнивать два массива с использованием операторов отношения. Результатом будет булевой массив, т. е. элемент в результирующем массиве будет иметь значение «True», только если условие выполнено. Пример показан ниже:
>>> c=n.array([[1,2],[3,4]])
>>> d=n.array([[1,3],[2,1]])
>>> c
array([[1, 2],
[3, 4]])
>>> d
array([[1, 3],
[2, 1]])
>>> c==d
array([[ True, False],
[False, False]], dtype=bool)
Логические операции: логические операции на массивах могут выполняться с использованием встроенных функций, поддерживаемых NumPy. Для этой цели можно использовать такие функции, как logic_or(), logical_not(), logical_and() и т. д. Фрагмент кода, приведенный ниже, показывает результаты выполнения операции XOR.
>>> c=n.array([[0,1],[2,3]])
>>> d=n.array([[1,3],[2,0]])
>>> n.logical_xor(c,d)
array([[ True, False],
[False, True]], dtype=bool)
Индексирование и разрезание массивов
Индекс массива NumPy начинается с 0. Пусть 'a' будет двумерным массивом. 'a [i][j]' представляет (j + 1)-й элемент в (i + 1)-й строке. Эквивалентно, вы можете записать его как ‘a[i,j]’. ‘a[3,:]’ представляет все элементы в 4-й строке. 'a[i:i+2, :]' представляет все элементы от (i + 1)-й строки до (i + 3)-й строки.
Теперь я собираюсь объяснить привлекательную особенность массивов NumPy, которая не что иное, как поддержка булевого индексирования. Приведенный ниже пример объясняет это.
>>> c=n.array([1,4,7,8,2])
>>> d=c<5
>>> d
array([ True, True, False, False, True], dtype=bool)
>>> c[d]
array([1, 4, 2])
Здесь «d» - это логический массив, чей элемент имеет значение «True», если соответствующий элемент в «c» имеет значение меньше 5. Обращение к массиву «c» с использованием «d», то есть c[d], будет выбирать элемент в 'c', только если элемент в соответствующей позиции индекса в 'd' равен 'True'. Приведу еще один пример. Массив «a» определяется следующим образом:
>>>a=n.array([1,2,3,4,5,6,7])
Мы видим, что приведенное ниже выражение будет извлекать все элементы в массиве 'a', которые являются четными числами.
>>> a[a%2==0]
array([2, 4, 6])
Переполнение целых чисел в Python
>>>a=n.array([2**63-1,4],dtype=int)
>>>a
array([9223372036854775807, 4])
>>>a+1
array([-9223372036854775808, 5])
В заключение можно сказать, что NumPy не только упрощает вычисления, но и ускоряет работу программ. Он обеспечивает многомерные массивы и инструменты для работы с массивами.
Комментариев нет:
Отправить комментарий