Что такое NumPy?
NumPy — это фундаментальный пакет для научных вычислений в Python. Это библиотека Python, которая предоставляет объект многомерного массива, различные производные объекты (такие как маскированные массивы и матрицы), а также набор функций для быстрых операций над массивами, включая математические, логические, манипуляции с формой, сортировку, выбор, ввод-вывод, дискретные преобразования Фурье, основные операции линейной алгебры, базовые статистические операции, моделирование случайных величин и многое другое.
В основе пакета NumPy лежит объект ndarray. Он представляет собой n-мерные массивы однородных типов данных, причём многие операции выполняются в скомпилированном коде для повышения производительности. Существуют некоторые важные различия между массивами NumPy и стандартными последовательностями Python:
- Массивы NumPy имеют фиксированный размер при создании, в отличие от списков Python (которые могут динамически расти). Изменение размера
ndarrayприведет к созданию нового массива и удалению исходного. - Элементы массива NumPy должны быть одного типа данных, и, следовательно, занимают одинаковое место в памяти. Исключение: можно иметь массивы объектов (Python, включая NumPy), что позволяет иметь массивы элементов различного размера.
- Массивы NumPy облегчают продвинутые математические и другие типы операций над большими объемами данных. Обычно такие операции выполняются более эффективно и с меньшим кодом, чем это возможно с помощью встроенных последовательностей Python.
- Всё больше научных и математических пакетов на базе Python используют массивы NumPy; хотя они обычно поддерживают ввод данных в виде последовательностей Python, они преобразуют такой ввод в массивы NumPy перед обработкой, и часто выводят массивы NumPy. Другими словами, для эффективного использования большинства (возможно, даже большей части) современных научных/математических программ на Python, знание того, как использовать встроенные типы последовательностей Python, недостаточно — необходимо также знать, как использовать массивы NumPy.
Моменты, связанные с размером последовательности и скоростью, особенно важны в научных вычислениях. В качестве простого примера рассмотрим случай умножения каждого элемента последовательности 1-D на соответствующий элемент другой последовательности такой же длины. Если данные хранятся в двух списках Python, a и b, мы могли бы перебирать каждый элемент:
c = []
for i in range(len(a)):
c.append(a[i]*b[i])
Это даёт правильный ответ, но если a и b содержат миллионы чисел, мы заплатим за неэффективность циклов в Python. Мы могли бы выполнить ту же задачу гораздо быстрее на языке C, написав (для ясности мы пренебрегаем объявлениями переменных и инициализацией, выделением памяти и т.д.)
for (i = 0; i < rows; i++): {
c[i] = a[i]*b[i];
}
Это экономит все накладные расходы, связанные с интерпретацией кода Python и манипулированием объектами Python, но за счёт преимущества программирования на Python. Более того, объём кода, необходимый для работы, увеличивается с размерностью наших данных. В случае 2-мерного массива, например, код на C (сокращённый, как и раньше) расширяется до
for (i = 0; i < rows; i++): {
for (j = 0; j < columns; j++): {
c[i][j] = a[i][j]*b[i][j];
}
}
NumPy даёт нам лучшее из обоих миров: элементные операции по умолчанию, когда задействован массив ndarray, но элементная операция выполняется быстро предварительно скомпилированным кодом C. В NumPy
c = a * b
делает то же, что и предыдущие примеры, со скоростью, близкой к скорости C, но с простотой кода, которую мы ожидаем от чего-то основанного на Python. Действительно, синтаксис NumPy ещё проще! Этот последний пример иллюстрирует две особенности NumPy, которые лежат в основе большей части его мощности: векторизация и трансляция.
Почему NumPy Быстрый?
Векторизация описывает отсутствие явных циклов, индексирования и т. д. в коде — эти вещи, конечно, происходят «за кулисами» в оптимизированном, предварительно скомпилированном коде C. Векторизованный код имеет много преимуществ, среди которых:
- векторизованный код более лаконичный и легче читается
- меньше строк кода, как правило, означает меньше ошибок
- код больше напоминает стандартную математическую запись (что делает его проще, как правило, правильно закодировать математические конструкции)
- векторизация приводит к более «питоновскому» коду. Без векторизации наш код был бы загромождён неэффективными и трудночитаемыми циклами
for.
Трансляция — это термин, используемый для описания неявного элементного поведения операций; в общем случае, в NumPy все операции, не только арифметические, но и логические, побитовые, функциональные и т. д., ведут себя неявным элементно-поэлементным образом, т. е. транслируются. Более того, в примере выше, a и b могут быть многомерными массивами одной формы, или скаляром и массивом, или даже двумя массивами с различными формами, при условии, что меньший массив «расширяем» до формы большего массива таким образом, чтобы полученная трансляция была однозначной. Более подробные «правила» трансляции см. в numpy.doc.broadcasting.
Кто ещё использует NumPy?
NumPy полностью поддерживает объектно-ориентированный подход, начиная, как и прежде, с ndarray. Например, ndarray — это класс, обладающий множеством методов и атрибутов. Многие из его методов дублируются функциями во внешнем пространстве имён NumPy, позволяя программисту работать в любой парадигме по своему выбору. Эта гибкость позволила диалекту массивов NumPy и классу NumPy ndarray стать фактическим языком многомерного обмена данными, используемым в Python.
© 2005–2020 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.18/user/whatisnumpy.html