NumPy: абсолютные основы для начинающих
Добро пожаловать в руководство для абсолютных новичков по NumPy! Если у вас есть комментарии или предложения, пожалуйста, не стесняйтесь обращаться!
Добро пожаловать в NumPy!
NumPy (Numerical Python) — это библиотека Python с открытым исходным кодом, которая используется практически во всех областях науки и техники. Это универсальный стандарт для работы с числовыми данными в Python, и он лежит в основе научных экосистем Python и PyData. Пользователи NumPy — это все, от начинающих программистов до опытных исследователей, занимающихся передовыми научными и промышленными исследованиями и разработками. API NumPy широко используется в Pandas, SciPy, Matplotlib, scikit-learn, scikit-image и большинстве других пакетов для анализа данных и научных вычислений на Python.
Библиотека NumPy содержит многомерные массивы и структуры данных матриц (подробнее об этом вы узнаете в последующих разделах). Она предоставляет ndarray, однородный n-мерный объект массива, с методами для эффективной работы с ним. NumPy можно использовать для выполнения широкого спектра математических операций над массивами. Он добавляет в Python мощные структуры данных, которые гарантируют эффективные вычисления с массивами и матрицами, и предоставляет огромную библиотеку математических функций высокого уровня, которые работают с этими массивами и матрицами.
Узнайте больше о NumPy здесь!
Установка NumPy
Для установки NumPy мы настоятельно рекомендуем использовать дистрибутив научного Python. Если вы ищете полные инструкции по установке NumPy в вашей операционной системе, вы можете найти все подробности здесь.
Если у вас уже установлен Python, вы можете установить NumPy с помощью:
conda install numpy
или
pip install numpy
Если у вас еще нет Python, вы можете рассмотреть возможность использования Anaconda. Это самый простой способ начать работу. Преимущество этого дистрибутива заключается в том, что вам не нужно беспокоиться об отдельной установке NumPy или любых основных пакетов, которые вы будете использовать для анализа данных, таких как pandas, Scikit-Learn и т. д.
Вы можете найти все подробности об установке в разделе Установка на сайте SciPy.
Как импортировать NumPy
Каждый раз, когда вы хотите использовать пакет или библиотеку в своем коде, вам сначала нужно сделать его доступным.
Чтобы начать использовать NumPy и все доступные в нем функции, вам нужно импортировать его. Это можно легко сделать с помощью этого оператора импорта:
import numpy as np
(Мы сокращаем numpy до np для экономии времени, а также для поддержания стандартизации кода, чтобы любой, кто работает с вашим кодом, мог легко понять и запустить его.)
Чтение кода примеров
Если вы еще не умеете читать учебники, содержащие много кода, вы можете не знать, как интерпретировать блок кода, который выглядит так:
>>> a = np.arange(6) >>> a2 = a[np.newaxis, :] >>> a2.shape (1, 6)
Если вы не знакомы с этим стилем, его очень легко понять. Если вы видите >>>, вы видите ввод или код, который вы бы ввели. Все, что не имеет >>> перед собой, является выводом или результатами выполнения вашего кода. Это стиль, который вы видите при запуске python в командной строке, но если вы используете IPython, вы можете увидеть другой стиль.
В чем разница между списком Python и массивом NumPy?
NumPy предоставляет огромный набор быстрых и эффективных способов создания массивов и обработки числовых данных внутри них. В то время как список Python может содержать разные типы данных в одном списке, все элементы массива NumPy должны быть однородными. Математические операции, которые должны выполняться над массивами, были бы чрезвычайно неэффективными, если бы массивы не были однородными.
Зачем использовать NumPy?
Массивы NumPy быстрее и компактнее, чем списки Python. Массив потребляет меньше памяти и удобен в использовании. NumPy использует гораздо меньше памяти для хранения данных и предоставляет механизм указания типов данных. Это позволяет еще больше оптимизировать код.
Что такое массив?
Массив — это центральная структура данных библиотеки NumPy. Массив представляет собой сетку значений, и он содержит информацию о необработанных данных, о том, как найти элемент, и о том, как интерпретировать элемент. Он имеет сетку элементов, которые можно индексировать разными способами. Все элементы имеют один и тот же тип, называемый типом массива dtype.
Массив может быть проиндексирован кортежем неотрицательных целых чисел, булевыми значениями, другим массивом или целыми числами. rank массива — это количество измерений. shape массива — это кортеж целых чисел, указывающий размер массива вдоль каждого измерения.
Один из способов инициализации массивов NumPy — это использование списков Python, используя вложенные списки для двумерных или многомерных данных.
Например:
>>> a = np.array([1, 2, 3, 4, 5, 6])
или:
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
Мы можем получить доступ к элементам массива, используя квадратные скобки. При доступе к элементам помните, что индексация в NumPy начинается с 0. Это означает, что если вы хотите получить доступ к первому элементу вашего массива, вы будете обращаться к элементу «0».
>>> print(a[0]) [1 2 3 4]
Дополнительная информация о массивах
Этот раздел охватывает 1D array, 2D array, ndarray, vector, matrix
Иногда вы можете услышать, что массив называется «ndarray», что является сокращением от «N-мерный массив». N-мерный массив — это просто массив с любым количеством измерений. Вы также можете услышать 1-D или одномерный массив, 2-D или двумерный массив и так далее. Класс NumPy ndarray используется для представления как матриц, так и векторов. Вектор — это массив с одним измерением (нет разницы между строчными и столбцовыми векторами), а матрица относится к массиву с двумя измерениями. Для 3-D или массивов с более высокими измерениями также часто используется термин тензор.
Какие атрибуты имеет массив?
Массив обычно представляет собой контейнер фиксированного размера элементов одного и того же типа и размера. Количество измерений и элементов в массиве определяется его формой. Форма массива — это кортеж неотрицательных целых чисел, указывающих размеры каждого измерения.
В NumPy измерения называются осями. Это означает, что если у вас есть двумерный массив, который выглядит так:
[[0., 0., 0.], [1., 1., 1.]]
Ваш массив имеет 2 оси. Первая ось имеет длину 2, а вторая ось имеет длину 3.
Как и в других объектах-контейнерах Python, доступ к содержимому массива и его изменение можно осуществлять путем индексации или среза массива. В отличие от типичных объектов-контейнеров, разные массивы могут совместно использовать одни и те же данные, поэтому изменения, внесенные в один массив, могут быть видны в другом.
Атрибуты массива отражают информацию, присущую самому массиву. Если вам нужно получить или даже установить свойства массива без создания нового массива, вы часто можете получить доступ к массиву через его атрибуты.
Узнайте больше об атрибутах массива здесь и узнайте о объектах массива здесь.
Как создать базовый массив
Этот раздел охватывает np.array(), np.zeros(), np.ones(), np.empty(), np.arange(), np.linspace(), dtype
Чтобы создать массив NumPy, вы можете использовать функцию np.array().
Все, что вам нужно сделать, чтобы создать простой массив, — это передать ему список. При желании вы также можете указать тип данных в своем списке. Вы можете найти больше информации о типах данных здесь.
>>> import numpy as np >>> a = np.array([1, 2, 3])
Вы можете визуализировать свой массив следующим образом:
Обратите внимание, что эти визуализации предназначены для упрощения идей и предоставления вам базового понимания концепций и механики NumPy. Массивы и операции с массивами гораздо сложнее, чем показано здесь!
Помимо создания массива из последовательности элементов, вы можете легко создать массив, заполненный 0:
>>> np.zeros(2) array([0., 0.])
Или массив, заполненный 1:
>>> np.ones(2) array([1., 1.])
Или даже пустой массив! Функция empty создает массив, исходное содержимое которого является случайным и зависит от состояния памяти. Причина использования empty вместо zeros (или чего-то подобного) — это скорость — просто убедитесь, что вы заполнили каждый элемент позже!
>>> # Create an empty array with 2 elements >>> np.empty(2) array([ 3.14, 42. ]) # may vary
Вы можете создать массив с диапазоном элементов:
>>> np.arange(4) array([0, 1, 2, 3])
И даже массив, содержащий диапазон равномерно распределенных интервалов. Для этого вы укажете первое число, последнее число и шаг.
>>> np.arange(2, 9, 2) array([2, 4, 6, 8])
Вы также можете использовать np.linspace() для создания массива со значениями, которые линейно распределены в указанном интервале:
>>> np.linspace(0, 10, num=5) array([ 0. , 2.5, 5. , 7.5, 10. ])
Указание типа данных
Хотя тип данных по умолчанию — с плавающей запятой (np.float64), вы можете явно указать нужный тип данных, используя ключевое слово dtype.
>>> x = np.ones(2, dtype=np.int64) >>> x array([1, 1])
Узнайте больше о создании массивов здесь
Добавление, удаление и сортировка элементов
Этот раздел охватывает np.sort(), np.concatenate()
Сортировка элемента проста с помощью np.sort(). Вы можете указать ось, тип и порядок при вызове функции.
Если вы начнете с этого массива:
>>> arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])
Вы можете быстро отсортировать числа в порядке возрастания с помощью:
>>> np.sort(arr) array([1, 2, 3, 4, 5, 6, 7, 8])
В дополнение к функции sort, которая возвращает отсортированную копию массива, вы можете использовать:
-
argsort, который представляет собой косвенную сортировку вдоль указанной оси, -
lexsort, который представляет собой косвенную стабильную сортировку по нескольким ключам, -
searchsorted, который находит элементы в отсортированном массиве, и -
partition, который представляет собой частичную сортировку.
Чтобы узнать больше о сортировке массива, см.: sort.
Если вы начнёте с этих массивов:
>>> a = np.array([1, 2, 3, 4]) >>> b = np.array([5, 6, 7, 8])
Вы можете объединить их с помощью np.concatenate().
>>> np.concatenate((a, b)) array([1, 2, 3, 4, 5, 6, 7, 8])
Или, если вы начнёте с этих массивов:
>>> x = np.array([[1, 2], [3, 4]]) >>> y = np.array([[5, 6]])
Вы можете объединить их с помощью:
>>> np.concatenate((x, y), axis=0)
array([[1, 2],
[3, 4],
[5, 6]])
Чтобы удалить элементы из массива, достаточно использовать индексацию для выбора элементов, которые вы хотите сохранить.
Чтобы узнать больше о конкатенации, см.: concatenate.
Как узнать форму и размер массива?
Этот раздел охватывает ndarray.ndim, ndarray.size, ndarray.shape
ndarray.ndim сообщит вам количество осей или измерений массива.
ndarray.size сообщит вам общее количество элементов массива. Это произведение элементов формы массива.
ndarray.shape отобразит кортеж целых чисел, указывающих количество элементов, хранящихся вдоль каждого измерения массива. Если, например, у вас есть двумерный массив с 2 строками и 3 столбцами, форма вашего массива будет (2, 3).
Например, если вы создадите этот массив:
>>> array_example = np.array([[[0, 1, 2, 3], ... [4, 5, 6, 7]], ... ... [[0, 1, 2, 3], ... [4, 5, 6, 7]], ... ... [[0 ,1 ,2, 3], ... [4, 5, 6, 7]]])
Чтобы найти количество измерений массива, выполните:
>>> array_example.ndim 3
Чтобы найти общее количество элементов в массиве, выполните:
>>> array_example.size 24
И чтобы найти форму вашего массива, выполните:
>>> array_example.shape (3, 2, 4)
Можно ли изменить форму массива?
Этот раздел охватывает arr.reshape()
Да!
Использование arr.reshape() придаст массиву новую форму, не изменяя данные. Просто помните, что при использовании метода reshape результирующий массив должен иметь такое же количество элементов, как и исходный массив. Если вы начнёте с массива из 12 элементов, вам нужно убедиться, что ваш новый массив также имеет в общей сложности 12 элементов.
Если вы начнёте с этого массива:
>>> a = np.arange(6) >>> print(a) [0 1 2 3 4 5]
Вы можете использовать reshape() для изменения формы вашего массива. Например, вы можете изменить форму этого массива на массив с тремя строками и двумя столбцами:
>>> b = a.reshape(3, 2) >>> print(b) [[0 1] [2 3] [4 5]]
С помощью np.reshape вы можете указать несколько необязательных параметров:
>>> numpy.reshape(a, newshape=(1, 6), order='C') array([[0, 1, 2, 3, 4, 5]])
a - это массив, который нужно изменить.
newshape - это новая форма, которую вы хотите получить. Вы можете указать целое число или кортеж целых чисел. Если вы укажете целое число, результатом будет массив этой длины. Форма должна быть совместима с исходной формой.
order: C означает чтение/запись элементов в порядке индексов, подобном C, F означает чтение/запись элементов в порядке индексов, подобном Fortran, A означает чтение/запись элементов в порядке индексов, подобном Fortran, если a является смежным в памяти в стиле Fortran, и в стиле C в противном случае. (Это необязательный параметр, и его не нужно указывать.)
Если вы хотите узнать больше о порядке C и Fortran, вы можете прочитать больше о внутренней организации массивов NumPy здесь. По существу, порядок C и Fortran связан с тем, как индексы соответствуют порядку, в котором массив хранится в памяти. В Fortran, при перемещении по элементам двумерного массива так, как он хранится в памяти, первый индекс является наиболее быстро изменяющимся индексом. Поскольку первый индекс переходит к следующей строке по мере его изменения, матрица хранится по одному столбцу за раз. Вот почему Fortran считается языком с порядком столбцов. В C, с другой стороны, последний индекс изменяется наиболее быстро. Матрица хранится по строкам, что делает её языком с порядком строк. То, что вы делаете для C или Fortran, зависит от того, важнее ли сохранить соглашение об индексации или не изменять порядок данных.
Узнайте больше о манипулировании формой здесь.
Как преобразовать одномерный массив в двумерный массив (как добавить новую ось к массиву)
Этот раздел охватывает np.newaxis, np.expand_dims
Вы можете использовать np.newaxis и np.expand_dims для увеличения размерности вашего существующего массива.
Использование np.newaxis увеличит размерность вашего массива на одно измерение при однократном использовании. Это означает, что одномерный массив станет двумерным массивом, двумерный массив станет трёхмерным массивом и так далее.
Например, если вы начнёте с этого массива:
>>> a = np.array([1, 2, 3, 4, 5, 6]) >>> a.shape (6,)
Вы можете использовать np.newaxis для добавления новой оси:
>>> a2 = a[np.newaxis, :] >>> a2.shape (1, 6)
Вы можете явно преобразовать одномерный массив с помощью вектора-строки или вектора-столбца, используя np.newaxis. Например, вы можете преобразовать одномерный массив в вектор-строку, вставив ось вдоль первого измерения:
>>> row_vector = a[np.newaxis, :] >>> row_vector.shape (1, 6)
Или, для вектора-столбца, вы можете вставить ось вдоль второго измерения:
>>> col_vector = a[:, np.newaxis] >>> col_vector.shape (6, 1)
Вы также можете расширить массив, вставив новую ось в указанную позицию с помощью np.expand_dims.
Например, если вы начнёте с этого массива:
>>> a = np.array([1, 2, 3, 4, 5, 6]) >>> a.shape (6,)
Вы можете использовать np.expand_dims для добавления оси в позицию индекса 1 с помощью:
>>> b = np.expand_dims(a, axis=1) >>> b.shape (6, 1)
Вы можете добавить ось в позицию индекса 0 с помощью:
>>> c = np.expand_dims(a, axis=0) >>> c.shape (1, 6)
Найдите дополнительную информацию о newaxis здесь и expand_dims по адресу expand_dims.
Индексация и срезы
Вы можете индексировать и делать срезы массивов NumPy так же, как вы можете делать срезы списков Python.
>>> data = np.array([1, 2, 3]) >>> data[1] 2 >>> data[0:2] array([1, 2]) >>> data[1:] array([2, 3]) >>> data[-2:] array([2, 3])
Вы можете визуализировать это так:
Возможно, вам потребуется взять часть вашего массива или определённые элементы массива для использования в дальнейших анализах или дополнительных операциях. Для этого вам нужно будет подмножество, срез и/или индекс ваших массивов.
Если вы хотите выбрать значения из вашего массива, которые удовлетворяют определённым условиям, это легко сделать с помощью NumPy.
Например, если вы начнёте с этого массива:
>>> a = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
Вы можете легко напечатать все значения в массиве, которые меньше 5.
>>> print(a[a < 5]) [1 2 3 4]
Вы также можете выбрать, например, числа, равные или большие 5, и использовать это условие для индексации массива.
>>> five_up = (a >= 5) >>> print(a[five_up]) [ 5 6 7 8 9 10 11 12]
Вы можете выбрать элементы, которые делятся на 2:
>>> divisible_by_2 = a[a%2==0] >>> print(divisible_by_2) [ 2 4 6 8 10 12]
Или вы можете выбрать элементы, которые удовлетворяют двум условиям, используя операторы & и |:
>>> c = a[(a > 2) & (a < 11)] >>> print(c) [ 3 4 5 6 7 8 9 10]
Вы также можете использовать логические операторы & и | для возврата булевых значений, указывающих, удовлетворяют ли значения в массиве определённому условию. Это может быть полезно с массивами, содержащими имена или другие категориальные значения.
>>> five_up = (a > 5) | (a == 5) >>> print(five_up) [[False False False False] [ True True True True] [ True True True True]]
Вы также можете использовать np.nonzero() для выбора элементов или индексов из массива.
Начиная с этого массива:
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
Вы можете использовать np.nonzero() для печати индексов элементов, которые, например, меньше 5:
>>> b = np.nonzero(a < 5) >>> print(b) (array([0, 0, 0, 0]), array([0, 1, 2, 3]))
В этом примере был возвращён кортеж массивов: по одному для каждого измерения. Первый массив представляет индексы строк, где находятся эти значения, а второй массив представляет индексы столбцов, где находятся значения.
Если вы хотите сгенерировать список координат, где существуют элементы, вы можете сжать массивы, перебрать список координат и напечатать их. Например:
>>> list_of_coordinates= list(zip(b[0], b[1])) >>> for coord in list_of_coordinates: ... print(coord) (0, 0) (0, 1) (0, 2) (0, 3)
Вы также можете использовать np.nonzero() для печати элементов в массиве, которые меньше 5, с помощью:
>>> print(a[b]) [1 2 3 4]
Если искомый элемент отсутствует в массиве, то возвращаемый массив индексов будет пустым. Например:
>>> not_there = np.nonzero(a == 42) >>> print(not_there) (array([], dtype=int64), array([], dtype=int64))
Узнайте больше об индексации и срезах здесь и здесь.
Подробнее об использовании функции nonzero см. по адресу: nonzero.
Как создать массив из существующих данных
Этот раздел охватывает slicing and indexing, np.vstack(), np.hstack(), np.hsplit(), .view(), copy()
Вы можете легко создать новый массив из части существующего массива.
Допустим, у вас есть этот массив:
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Вы можете создать новый массив из части вашего массива в любое время, указав, где вы хотите сделать срез вашего массива.
>>> arr1 = a[3:8] >>> arr1 array([4, 5, 6, 7, 8])
Здесь вы взяли часть вашего массива с позиции индекса 3 до позиции индекса 8.
Вы также можете объединить два существующих массива как вертикально, так и горизонтально. Допустим, у вас есть два массива, a1 и a2:
>>> a1 = np.array([[1, 1], ... [2, 2]]) >>> a2 = np.array([[3, 3], ... [4, 4]])
Вы можете объединить их вертикально с помощью vstack:
>>> np.vstack((a1, a2))
array([[1, 1],
[2, 2],
[3, 3],
[4, 4]])
Или объединить их горизонтально с помощью hstack:
>>> np.hstack((a1, a2))
array([[1, 1, 3, 3],
[2, 2, 4, 4]])
Вы можете разделить массив на несколько меньших массивов, используя hsplit. Вы можете указать либо количество массивов одинаковой формы для возврата, либо столбцы, после которых должно произойти разделение.
Допустим, у вас есть этот массив:
>>> x = np.arange(1, 25).reshape(2, 12)
>>> x
array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]])
Если вы хотите разделить этот массив на три массива одинаковой формы, вы должны выполнить:
>>> np.hsplit(x, 3)
[array([[1, 2, 3, 4],
[13, 14, 15, 16]]), array([[ 5, 6, 7, 8],
[17, 18, 19, 20]]), array([[ 9, 10, 11, 12],
[21, 22, 23, 24]])]
Если вы хотите разделить ваш массив после третьего и четвёртого столбца, вы должны выполнить:
>>> np.hsplit(x, (3, 4))
[array([[1, 2, 3],
[13, 14, 15]]), array([[ 4],
[16]]), array([[ 5, 6, 7, 8, 9, 10, 11, 12],
[17, 18, 19, 20, 21, 22, 23, 24]])]
Узнайте больше о склеивании и разделении массивов здесь.
Вы можете использовать метод view для создания нового объекта массива, который ссылается на те же данные, что и исходный массив (неглубокая копия).
Представления являются важной концепцией NumPy! Функции NumPy, а также операции, такие как индексирование и срезы, будут возвращать представления, когда это возможно. Это экономит память и работает быстрее (не нужно создавать копию данных). Однако важно помнить об этом — изменение данных в представлении также изменяет исходный массив!
Допустим, вы создали этот массив:
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
Теперь мы создаем массив b1 с помощью среза a и изменяем первый элемент b1. Это также изменит соответствующий элемент в a!
>>> b1 = a[0, :]
>>> b1
array([1, 2, 3, 4])
>>> b1[0] = 99
>>> b1
array([99, 2, 3, 4])
>>> a
array([[99, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
Использование метода copy создаст полную копию массива и его данных (глубокая копия). Чтобы использовать это в вашем массиве, вы можете выполнить:
>>> b2 = a.copy()
Узнайте больше о копиях и представлениях здесь.
Основные операции с массивами
В этом разделе рассматриваются сложение, вычитание, умножение, деление и многое другое
После создания массивов вы можете начать с ними работать. Допустим, например, что вы создали два массива, один называется «data», а другой — «ones»
Вы можете сложить массивы вместе с помощью знака плюс.
>>> data = np.array([1, 2]) >>> ones = np.ones(2, dtype=int) >>> data + ones array([2, 3])
Конечно, вы можете делать больше, чем просто сложение!
>>> data - ones array([0, 1]) >>> data * data array([1, 4]) >>> data / data array([1., 1.])
Основные операции просты с NumPy. Если вы хотите найти сумму элементов в массиве, вы будете использовать sum(). Это работает для одномерных массивов, двумерных массивов и массивов более высоких размерностей.
>>> a = np.array([1, 2, 3, 4]) >>> a.sum() 10
Чтобы сложить строки или столбцы в двумерном массиве, вы укажете ось.
Если вы начинаете с этого массива:
>>> b = np.array([[1, 1], [2, 2]])
Вы можете суммировать строки с помощью:
>>> b.sum(axis=0) array([3, 3])
Вы можете суммировать столбцы с помощью:
>>> b.sum(axis=1) array([2, 4])
Узнайте больше об основных операциях здесь.
Broadcasting
Иногда вам может потребоваться выполнить операцию между массивом и одним числом (также называемым операцией между вектором и скаляром) или между массивами разных размеров. Например, ваш массив (мы назовем его «data») может содержать информацию о расстоянии в милях, но вы хотите преобразовать информацию в километры. Вы можете выполнить эту операцию с помощью:
>>> data = np.array([1.0, 2.0]) >>> data * 1.6 array([1.6, 3.2])
NumPy понимает, что умножение должно произойти с каждой ячейкой. Эта концепция называется broadcasting. Broadcasting — это механизм, который позволяет NumPy выполнять операции над массивами разных форм. Размеры вашего массива должны быть совместимы, например, когда размеры обоих массивов равны или когда один из них равен 1. Если размеры несовместимы, вы получите ValueError.
Узнайте больше о broadcasting здесь.
Более полезные операции с массивами
В этом разделе рассматриваются максимум, минимум, сумма, среднее, произведение, стандартное отклонение и многое другое
NumPy также выполняет агрегационные функции. В дополнение к min, max и sum, вы можете легко запустить mean для получения среднего значения, prod для получения результата умножения элементов, std для получения стандартного отклонения и многое другое.
>>> data.max() 2.0 >>> data.min() 1.0 >>> data.sum() 3.0
Начнем с этого массива, называемого «a»
>>> a = np.array([[0.45053314, 0.17296777, 0.34376245, 0.5510652], ... [0.54627315, 0.05093587, 0.40067661, 0.55645993], ... [0.12697628, 0.82485143, 0.26590556, 0.56917101]])
Очень часто требуется агрегировать по строке или столбцу. По умолчанию каждая агрегационная функция NumPy возвращает агрегат всего массива. Чтобы найти сумму или минимум элементов в вашем массиве, выполните:
>>> a.sum() 4.8595784
Или:
>>> a.min() 0.05093587
Вы можете указать, на какой оси вы хотите вычислить агрегатную функцию. Например, вы можете найти минимальное значение в каждом столбце, указав axis=0.
>>> a.min(axis=0) array([0.12697628, 0.05093587, 0.26590556, 0.5510652 ])
Четыре значения, перечисленные выше, соответствуют количеству столбцов в вашем массиве. С четырехстолбцовым массивом вы получите четыре значения в качестве результата.
Подробнее о методах массива здесь.
Создание матриц
Вы можете передать списки списков Python для создания двумерного массива (или «матрицы») для их представления в NumPy.
>>> data = np.array([[1, 2], [3, 4]])
>>> data
array([[1, 2],
[3, 4]])
Операции индексирования и срезов полезны при работе с матрицами:
>>> data[0, 1] 2 >>> data[1:3] array([[3, 4]]) >>> data[0:2, 0] array([1, 3])
Вы можете агрегировать матрицы так же, как вы агрегировали векторы:
>>> data.max() 4 >>> data.min() 1 >>> data.sum() 10
Вы можете агрегировать все значения в матрице, а также агрегировать их по столбцам или строкам, используя параметр axis:
>>> data.max(axis=0) array([3, 4]) >>> data.max(axis=1) array([2, 4])
После создания матриц вы можете складывать и умножать их с помощью арифметических операторов, если у вас есть две матрицы одинакового размера.
>>> data = np.array([[1, 2], [3, 4]])
>>> ones = np.array([[1, 1], [1, 1]])
>>> data + ones
array([[2, 3],
[4, 5]])
Вы можете выполнять эти арифметические операции над матрицами разных размеров, но только если одна матрица имеет только один столбец или одну строку. В этом случае NumPy будет использовать свои правила вещания для операции.
>>> data = np.array([[1, 2], [3, 4], [5, 6]])
>>> ones_row = np.array([[1, 1]])
>>> data + ones_row
array([[2, 3],
[4, 5],
[6, 7]])
Обратите внимание, что когда NumPy печатает N-мерные массивы, последняя ось перебирается быстрее, а первая ось — медленнее. Например:
>>> np.ones((4, 3, 2))
array([[[1., 1.],
[1., 1.],
[1., 1.]],
[[1., 1.],
[1., 1.],
[1., 1.]],
[[1., 1.],
[1., 1.],
[1., 1.]],
[[1., 1.],
[1., 1.],
[1., 1.]]])
Часто бывают случаи, когда нам нужно, чтобы NumPy инициализировал значения массива. NumPy предлагает функции, такие как ones() и zeros(), и класс random.Generator для генерации случайных чисел. Все, что вам нужно сделать, это передать количество элементов, которые вы хотите сгенерировать:
>>> np.ones(3) array([1., 1., 1.]) >>> np.zeros(3) array([0., 0., 0.]) # the simplest way to generate random numbers >>> rng = np.random.default_rng(0) >>> rng.random(3) array([0.63696169, 0.26978671, 0.04097352])
Вы также можете использовать ones(), zeros() и random() для создания двумерного массива, если вы передадите им кортеж, описывающий размеры матрицы:
>>> np.ones((3, 2))
array([[1., 1.],
[1., 1.],
[1., 1.]])
>>> np.zeros((3, 2))
array([[0., 0.],
[0., 0.],
[0., 0.]])
>>> rng.random((3, 2))
array([[0.01652764, 0.81327024],
[0.91275558, 0.60663578],
[0.72949656, 0.54362499]]) # may vary
Подробнее о создании массивов, заполненных 0, 1, другими значениями или неинициализированными, см. в разделе процедуры создания массивов.
Генерация случайных чисел
Использование генерации случайных чисел является важной частью конфигурации и оценки многих численных и алгоритмов машинного обучения. Независимо от того, нужно ли вам случайным образом инициализировать веса в искусственной нейронной сети, разделять данные на случайные наборы или случайным образом перемешивать ваш набор данных, способность генерировать случайные числа (фактически, повторяемые псевдослучайные числа) необходима.
С помощью Generator.integers вы можете генерировать случайные целые числа от low (помните, что это включительно с NumPy) до high (исключительно). Вы можете установить endpoint=True, чтобы сделать высокое число включительным.
Вы можете сгенерировать 2 x 4 массив случайных целых чисел от 0 до 4 с помощью:
>>> rng.integers(5, size=(2, 4))
array([[2, 1, 1, 0],
[0, 0, 0, 4]]) # may vary
Узнайте больше о генерации случайных чисел здесь.
Как получить уникальные элементы и их количество
В этом разделе рассматриваются np.unique()
Вы можете легко найти уникальные элементы в массиве с помощью np.unique.
Например, если вы начинаете с этого массива:
>>> a = np.array([11, 11, 12, 13, 14, 15, 16, 17, 12, 13, 11, 14, 18, 19, 20])
вы можете использовать np.unique для вывода уникальных значений в вашем массиве:
>>> unique_values = np.unique(a) >>> print(unique_values) [11 12 13 14 15 16 17 18 19 20]
Чтобы получить индексы уникальных значений в массиве NumPy (массив первых индексных позиций уникальных значений в массиве), просто передайте аргумент return_index в np.unique(), а также ваш массив.
>>> unique_values, indices_list = np.unique(a, return_index=True) >>> print(indices_list) [ 0 2 3 4 5 6 7 12 13 14]
Вы можете передать аргумент return_counts в np.unique() вместе с вашим массивом, чтобы получить частоту уникальных значений в массиве NumPy.
>>> unique_values, occurrence_count = np.unique(a, return_counts=True) >>> print(occurrence_count) [3 2 2 2 1 1 1 1 1 1]
Это также работает с двумерными массивами! Если вы начинаете с этого массива:
>>> a_2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]])
Вы можете найти уникальные значения с помощью:
>>> unique_values = np.unique(a_2d) >>> print(unique_values) [ 1 2 3 4 5 6 7 8 9 10 11 12]
Если аргумент оси не передан, ваш двумерный массив будет сглажен.
Если вы хотите получить уникальные строки или столбцы, обязательно передайте аргумент axis. Чтобы найти уникальные строки, укажите axis=0, а для столбцов укажите axis=1.
>>> unique_rows = np.unique(a_2d, axis=0) >>> print(unique_rows) [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]]
Чтобы получить уникальные строки, индексную позицию и количество вхождений, вы можете использовать:
>>> unique_rows, indices, occurrence_count = np.unique( ... a_2d, axis=0, return_counts=True, return_index=True) >>> print(unique_rows) [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] >>> print(indices) [0 1 2] >>> print(occurrence_count) [2 1 1]
Чтобы узнать больше о поиске уникальных элементов в массиве, см. unique.
Транспонирование и изменение формы матрицы
В этом разделе рассматриваются arr.reshape(), arr.transpose(), arr.T()
Часто необходимо транспонировать ваши матрицы. Массивы NumPy имеют свойство T, которое позволяет транспонировать матрицу.
Вам также может потребоваться изменить размерность матрицы. Это может произойти, например, когда у вас есть модель, которая ожидает определенную форму входных данных, которая отличается от вашего набора данных. Именно здесь может быть полезен метод reshape. Вам просто нужно передать новые размеры, которые вы хотите для матрицы.
>>> data.reshape(2, 3)
array([[1, 2, 3],
[4, 5, 6]])
>>> data.reshape(3, 2)
array([[1, 2],
[3, 4],
[5, 6]])
Вы также можете использовать .transpose для обращения или изменения осей массива в соответствии со значениями, которые вы указываете.
Если вы начинаете с этого массива:
>>> arr = np.arange(6).reshape((2, 3))
>>> arr
array([[0, 1, 2],
[3, 4, 5]])
Вы можете транспонировать ваш массив с помощью arr.transpose().
>>> arr.transpose()
array([[0, 3],
[1, 4],
[2, 5]])
Чтобы узнать больше о транспонировании и изменении формы массивов, см. transpose и reshape.
Как развернуть массив
В этом разделе рассматриваются np.flip
Функция np.flip() NumPy позволяет переворачивать или разворачивать содержимое массива вдоль оси. При использовании np.flip укажите массив, который вы хотите развернуть, и ось. Если вы не указываете ось, NumPy развернет содержимое вдоль всех осей входного массива.
Развертывание одномерного массива
Если вы начинаете с одномерного массива, такого как этот:
>>> arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
Вы можете обратить его с помощью:
>>> reversed_arr = np.flip(arr)
Если вы хотите распечатать ваш перевернутый массив, вы можете запустить:
>>> print('Reversed Array: ', reversed_arr)
Reversed Array: [8 7 6 5 4 3 2 1]
Обращение двумерного массива
Двумерный массив работает почти так же.
Если вы начинаете с этого массива:
>>> arr_2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
Вы можете обратить содержимое во всех строках и во всех столбцах с помощью:
>>> reversed_arr = np.flip(arr_2d) >>> print(reversed_arr) [[12 11 10 9] [ 8 7 6 5] [ 4 3 2 1]]
Вы можете легко обратить только строки с помощью:
>>> reversed_arr_rows = np.flip(arr_2d, axis=0) >>> print(reversed_arr_rows) [[ 9 10 11 12] [ 5 6 7 8] [ 1 2 3 4]]
Или обратить только столбцы с помощью:
>>> reversed_arr_columns = np.flip(arr_2d, axis=1) >>> print(reversed_arr_columns) [[ 4 3 2 1] [ 8 7 6 5] [12 11 10 9]]
Вы также можете обратить содержимое только одного столбца или строки. Например, вы можете обратить содержимое строки в позиции индекса 1 (вторая строка):
>>> arr_2d[1] = np.flip(arr_2d[1]) >>> print(arr_2d) [[ 1 2 3 4] [ 8 7 6 5] [ 9 10 11 12]]
Вы также можете обратить столбец в позиции индекса 1 (второй столбец):
>>> arr_2d[:,1] = np.flip(arr_2d[:,1]) >>> print(arr_2d) [[ 1 10 3 4] [ 8 7 6 5] [ 9 2 11 12]]
Подробнее об обращении массивов читайте в flip.
Изменение формы и выравнивание многомерных массивов
Этот раздел охватывает .flatten(), ravel()
Есть два популярных способа выровнять массив: .flatten() и .ravel(). Основное различие между ними заключается в том, что новый массив, созданный с помощью ravel(), фактически является ссылкой на родительский массив (т.е. «представлением»). Это означает, что любые изменения в новом массиве также повлияют на родительский массив. Поскольку ravel не создает копию, это эффективно с точки зрения памяти.
Если вы начинаете с этого массива:
>>> x = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
Вы можете использовать flatten для выравнивания вашего массива в одномерный массив.
>>> x.flatten() array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
Когда вы используете flatten, изменения в вашем новом массиве не изменят родительский массив.
Например:
>>> a1 = x.flatten() >>> a1[0] = 99 >>> print(x) # Original array [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] >>> print(a1) # New array [99 2 3 4 5 6 7 8 9 10 11 12]
Но когда вы используете ravel, изменения, которые вы вносите в новый массив, повлияют на родительский массив.
Например:
>>> a2 = x.ravel() >>> a2[0] = 98 >>> print(x) # Original array [[98 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] >>> print(a2) # New array [98 2 3 4 5 6 7 8 9 10 11 12]
Подробнее о flatten читайте в ndarray.flatten и о ravel в ravel.
Как получить доступ к docstring для получения дополнительной информации
Этот раздел охватывает help(), ?, ??
Когда речь заходит об экосистеме науки о данных, Python и NumPy созданы с учетом пользователя. Один из лучших примеров этого — встроенный доступ к документации. Каждый объект содержит ссылку на строку, которая известна как docstring. В большинстве случаев этот docstring содержит краткое и лаконичное описание объекта и как его использовать. Python имеет встроенную функцию help(), которая может помочь вам получить доступ к этой информации. Это означает, что почти каждый раз, когда вам нужна дополнительная информация, вы можете использовать help() для быстрого поиска необходимой информации.
Например:
>>> help(max)
Help on built-in function max in module builtins:
max(...)
max(iterable, *[, default=obj, key=func]) -> value
max(arg1, arg2, *args, *[, key=func]) -> value
With a single iterable argument, return its biggest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the largest argument.
Поскольку доступ к дополнительной информации очень полезен, IPython использует символ ? в качестве сокращения для доступа к этой документации вместе с другой соответствующей информацией. IPython — это командная оболочка для интерактивных вычислений на нескольких языках. Вы можете найти больше информации о IPython здесь.
Например:
In [0]: max? max(iterable, *[, default=obj, key=func]) -> value max(arg1, arg2, *args, *[, key=func]) -> value With a single iterable argument, return its biggest item. The default keyword-only argument specifies an object to return if the provided iterable is empty. With two or more arguments, return the largest argument. Type: builtin_function_or_method
Вы можете использовать это обозначение даже для методов объекта и самих объектов.
Допустим, вы создали этот массив:
>>> a = np.array([1, 2, 3, 4, 5, 6])
Затем вы можете получить много полезной информации (сначала подробности о самом a, а затем docstring ndarray, экземпляром которого является a):
In [1]: a?
Type: ndarray
String form: [1 2 3 4 5 6]
Length: 6
File: ~/anaconda3/lib/python3.7/site-packages/numpy/__init__.py
Docstring: <no docstring>
Class docstring:
ndarray(shape, dtype=float, buffer=None, offset=0,
strides=None, order=None)
An array object represents a multidimensional, homogeneous array
of fixed-size items. An associated data-type object describes the
format of each element in the array (its byte-order, how many bytes it
occupies in memory, whether it is an integer, a floating point number,
or something else, etc.)
Arrays should be constructed using `array`, `zeros` or `empty` (refer
to the See Also section below). The parameters given here refer to
a low-level method (`ndarray(...)`) for instantiating an array.
For more information, refer to the `numpy` module and examine the
methods and attributes of an array.
Parameters
----------
(for the __new__ method; see Notes below)
shape : tuple of ints
Shape of created array.
...
Это также работает для функций и других объектов, которые вы создаете. Просто не забудьте включить docstring в свою функцию, используя строковый литерал (""" """ или ''' ''' вокруг вашей документации).
Например, если вы создадите эту функцию:
>>> def double(a): ... '''Return a * 2''' ... return a * 2
Вы можете получить информацию о функции:
In [2]: double? Signature: double(a) Docstring: Return a * 2 File: ~/Desktop/<ipython-input-23-b5adf20be596> Type: function
Вы можете достичь другого уровня информации, прочитав исходный код интересующего вас объекта. Использование двойного знака вопроса (??) позволяет вам получить доступ к исходному коду.
Например:
In [3]: double??
Signature: double(a)
Source:
def double(a):
'''Return a * 2'''
return a * 2
File: ~/Desktop/<ipython-input-23-b5adf20be596>
Type: function
Если рассматриваемый объект скомпилирован на языке, отличном от Python, использование ?? вернет ту же информацию, что и ?. Вы найдете это во многих встроенных объектах и типах, например:
In [4]: len? Signature: len(obj, /) Docstring: Return the number of items in a container. Type: builtin_function_or_method
и :
In [5]: len?? Signature: len(obj, /) Docstring: Return the number of items in a container. Type: builtin_function_or_method
имеют одинаковый вывод, потому что они были скомпилированы на языке программирования, отличном от Python.
Работа с математическими формулами
Простота реализации математических формул, работающих с массивами, — одна из причин широкого использования NumPy в научном сообществе Python.
Например, это формула среднеквадратичной ошибки (основная формула, используемая в моделях контролируемого машинного обучения, которые имеют дело с регрессией):
Реализация этой формулы в NumPy проста и понятна:
Что делает это так хорошо, так это то, что predictions и labels могут содержать одно или тысячу значений. Им нужно только быть одинакового размера.
Вы можете визуализировать это так:
В этом примере векторы предсказаний и меток содержат три значения, что означает, что n имеет значение три. После того, как мы выполним вычитание, значения в векторе возводятся в квадрат. Затем NumPy суммирует значения, и ваш результат — это значение ошибки для этого предсказания и оценка качества модели.
Как сохранять и загружать объекты NumPy
Этот раздел охватывает np.save, np.savez, np.savetxt, np.load, np.loadtxt
В какой-то момент вы захотите сохранить ваши массивы на диск и загрузить их обратно, не запуская код повторно. К счастью, есть несколько способов сохранять и загружать объекты с помощью NumPy. Объекты ndarray могут быть сохранены и загружены из файлов на диске с помощью функций loadtxt и savetxt, которые обрабатывают обычные текстовые файлы, функций load и save, которые обрабатывают двоичные файлы NumPy с расширением файла .npy, и функции savez, которая обрабатывает файлы NumPy с расширением файла .npz.
Файлы .npy и .npz хранят данные, форму, тип данных и другую информацию, необходимую для реконструкции ndarray таким образом, который позволяет правильно извлекать массив, даже когда файл находится на другой машине с другой архитектурой.
Если вы хотите сохранить один объект ndarray, сохраните его как файл .npy, используя np.save. Если вы хотите сохранить более одного объекта ndarray в одном файле, сохраните его как файл .npz, используя np.savez. Вы также можете сохранить несколько массивов в один файл в сжатом формате npz с помощью savez_compressed.
Легко сохранить и загрузить массив с помощью np.save(). Просто убедитесь, что вы указали массив, который хотите сохранить, и имя файла. Например, если вы создадите этот массив:
>>> a = np.array([1, 2, 3, 4, 5, 6])
Вы можете сохранить его как «filename.npy» с помощью:
>>> np.save('filename', a)
Вы можете использовать np.load() для реконструкции вашего массива.
>>> b = np.load('filename.npy')
Если вы хотите проверить свой массив, вы можете запустить::
>>> print(b) [1 2 3 4 5 6]
Вы можете сохранить массив NumPy как обычный текстовый файл, например файл .csv или .txt, с помощью np.savetxt.
Например, если вы создадите этот массив:
>>> csv_arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
Вы можете легко сохранить его как файл .csv с именем «new_file.csv» следующим образом:
>>> np.savetxt('new_file.csv', csv_arr)
Вы можете быстро и легко загрузить сохраненный текстовый файл, используя loadtxt().
>>> np.loadtxt('new_file.csv')
array([1., 2., 3., 4., 5., 6., 7., 8.])
Функции savetxt() и loadtxt() принимают дополнительные необязательные параметры, такие как заголовок, нижний колонтитул и разделитель. Хотя текстовые файлы могут быть проще для обмена, файлы .npy и .npz меньше и быстрее для чтения. Если вам требуется более сложная обработка вашего текстового файла (например, если вам нужно работать со строками, содержащими недостающие значения), вам следует использовать функцию genfromtxt.
С помощью savetxt вы можете указывать заголовки, нижние колонтитулы, комментарии и многое другое.
Узнайте больше о процедурах ввода и вывода здесь.
Импорт и экспорт CSV
Проще всего прочитать CSV-файл, содержащий существующую информацию. Лучший и самый простой способ сделать это — использовать Pandas.
>>> import pandas as pd
>>> # If all of your columns are the same type:
>>> x = pd.read_csv('music.csv', header=0).values
>>> print(x)
[['Billie Holiday' 'Jazz' 1300000 27000000]
['Jimmie Hendrix' 'Rock' 2700000 70000000]
['Miles Davis' 'Jazz' 1500000 48000000]
['SIA' 'Pop' 2000000 74000000]]
>>> # You can also simply select the columns you need:
>>> x = pd.read_csv('music.csv', usecols=['Artist', 'Plays']).values
>>> print(x)
[['Billie Holiday' 27000000]
['Jimmie Hendrix' 70000000]
['Miles Davis' 48000000]
['SIA' 74000000]]
Pandas также легко использовать для экспорта вашего массива. Если вы новичок в NumPy, вы можете создать фрейм данных Pandas из значений в вашем массиве, а затем записать фрейм данных в CSV-файл с помощью Pandas.
Если вы создали этот массив «a»
>>> a = np.array([[-2.58289208, 0.43014843, -1.24082018, 1.59572603], ... [ 0.99027828, 1.17150989, 0.94125714, -0.14692469], ... [ 0.76989341, 0.81299683, -0.95068423, 0.11769564], ... [ 0.20484034, 0.34784527, 1.96979195, 0.51992837]])
Вы можете создать фрейм данных Pandas
>>> df = pd.DataFrame(a)
>>> print(df)
0 1 2 3
0 -2.582892 0.430148 -1.240820 1.595726
1 0.990278 1.171510 0.941257 -0.146925
2 0.769893 0.812997 -0.950684 0.117696
3 0.204840 0.347845 1.969792 0.519928
Вы можете легко сохранить свой фрейм данных с помощью:
>>> df.to_csv('pd.csv')
И прочитать ваш CSV с помощью:
>>> data = pd.read_csv('pd.csv')
Вы также можете сохранить свой массив с помощью метода NumPy savetxt.
>>> np.savetxt('np.csv', a, fmt='%.2f', delimiter=',', header='1, 2, 3, 4')
Если вы используете командную строку, вы можете читать сохраненный CSV в любое время с помощью команды, например:
$ cat np.csv # 1, 2, 3, 4 -2.58,0.43,-1.24,1.60 0.99,1.17,0.94,-0.15 0.77,0.81,-0.95,0.12 0.20,0.35,1.97,0.52
Или вы можете открыть файл в любое время с помощью текстового редактора!
Если вы заинтересованы в изучении Pandas, ознакомьтесь с официальной документацией Pandas. Узнайте, как установить Pandas, с помощью официальной информации об установке Pandas.
Построение графиков массивов с помощью Matplotlib
Если вам нужно построить график ваших значений, это очень просто с помощью Matplotlib.
Например, у вас может быть массив, похожий на этот:
>>> a = np.array([2, 1, 5, 7, 4, 6, 8, 14, 10, 9, 18, 20, 22])
Если у вас уже установлен Matplotlib, вы можете импортировать его с помощью:
>>> import matplotlib.pyplot as plt # If you're using Jupyter Notebook, you may also want to run the following # line of code to display your code in the notebook: %matplotlib inline
Все, что вам нужно сделать, чтобы построить график ваших значений, это запустить:
>>> plt.plot(a) # If you are running from a command line, you may need to do this: # >>> plt.show()
Например, вы можете построить одномерный массив следующим образом:
>>> x = np.linspace(0, 5, 20) >>> y = np.linspace(0, 10, 20) >>> plt.plot(x, y, 'purple') # line >>> plt.plot(x, y, 'o') # dots
С помощью Matplotlib у вас есть доступ к огромному количеству вариантов визуализации.
>>> from mpl_toolkits.mplot3d import Axes3D >>> fig = plt.figure() >>> ax = Axes3D(fig) >>> X = np.arange(-5, 5, 0.15) >>> Y = np.arange(-5, 5, 0.15) >>> X, Y = np.meshgrid(X, Y) >>> R = np.sqrt(X**2 + Y**2) >>> Z = np.sin(R) >>> ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='viridis')
Чтобы узнать больше о Matplotlib и его возможностях, ознакомьтесь с официальной документацией. Инструкции по установке Matplotlib см. в официальном разделе установки.
Источники изображений: Jay Alammar http://jalammar.github.io/
© 2005–2020 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.19/user/absolute_beginners.html