Массивы NumPy: введение [с примерами]

Опубликовано: 2022-12-08

Хотите начать работу с NumPy? Это руководство научит вас основам работы с массивами NumPy в Python.

В качестве первого шага вы узнаете, чем массивы NumPy работают иначе, чем списки Python. Затем вы узнаете несколько способов создания массивов NumPy и выполнения основных операций с ними.

Давайте начнем!

Основы массивов NumPy

NumPy — одна из самых популярных библиотек Python для научных вычислений и анализа данных. Базовыми структурами данных в NumPy являются N-мерные массивы (массивы ND). Они имеют возможности вещания и позволяют нам векторизовать операции для увеличения скорости и использовать встроенные математические функции для повышения производительности.

Чтобы начать работу с NumPy, вы должны сначала установить библиотеку и импортировать ее в свою рабочую среду. Он доступен в виде пакета PyPI, который можно установить через pip.

Чтобы установить NumPy, откройте терминал и выполните следующую команду:

 pip3 install numpy

После установки NumPy вы можете импортировать его в свою рабочую среду под псевдонимом. Обычный псевдоним — np .

 import numpy as np

Примечание . Импорт NumPy под псевдонимом np является не обязательным, а рекомендуемым соглашением.

Списки Python против массивов NumPy

Рассмотрим следующий список чисел Python:

 py_list = [1,2,3,4]

Вы можете получить массив NumPy из существующего списка, вызвав np.array() со списком в качестве аргумента.

 np_arr1 = np.array(py_list) print(np_arr1) [1 2 3 4]

Чтобы проверить тип np_arr1 , вы вызываете встроенную функцию type() , вы увидите, что это ndarray , основная структура данных в NumPy.

 type(np_arr1) # numpy.ndarray

Хотя список Python и массив NumPy могут выглядеть одинаково, между ними есть определенные различия:

  • Список Python может содержать объекты разных типов данных, тогда как массив NumPy содержит элементы одного типа данных. Тип данных по умолчанию — float с точностью 64 бита (float64).
  • Элементы списка Python не обязательно хранятся в смежных местах в памяти. Однако элементы массива NumPy хранятся в непрерывном блоке памяти. В результате поиск и доступ к элементам происходит быстрее.

Давайте рассмотрим еще пару отличий.

Вещание

Мощная функция массивов NumPy — широковещательная рассылка. Предположим, мы хотим добавить 2 ко всем элементам np_arr1 и py_list .

Давайте попробуем добавить 2 в py_list и посмотрим, что произойдет:

 >>> py_list + 2

Мы видим, что мы получаем TypeError о том, что мы можем объединить только два списка, и добавление py_list + 2, подобное этому, не поддерживается.

 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-5-c0f9974899df> in <module> ----> 1 py_list + 2 TypeError: can only concatenate list (not "int") to list

Давайте попробуем ту же операцию с массивом np_arr1 .

 >>> np_arr1 + 2

В результате мы видим, что к каждому элементу массива прибавилось 2.

 array([3, 4, 5, 6])

Это связано с тем, что NumPy неявно передает скаляр 2 в массив совместимой формы, чтобы получить этот результат.

Векторизация

Массивы NumPy поддерживают векторизацию для более быстрых поэлементных операций. Предположим, мы хотим найти поэлементную сумму двух массивов.

Использование простой операции + в списке вернет конкатенацию двух списков (а это не то, что нам нужно!).

 >>> py_list + py_list # [1, 2, 3, 4, 1, 2, 3, 4]

Но та же операция с массивом NumPy, np_arr1 , возвращает поэлементную сумму np_arr1 с самим собой.

 >>> np_arr1 + np_arr1 # array([2, 4, 6, 8])

Точно так же вложенные списки могут быть похожи по структуре на N-мерный массив NumPy. Однако различия, обсуждавшиеся до сих пор, сохраняются.

 nested_list = [[1,2],[3,4],[5,6]] np_arr2 = np.array(nested_list) print(np_arr2)
 [[1 2] [3 4] [5 6]]

Как создать массивы NumPy

Вы всегда можете создавать массивы NumPy из существующих списков Python, используя np.array(list-obj) . Однако это не самый эффективный способ.

Вместо этого вы можете использовать несколько встроенных функций, позволяющих создавать массивы определенной формы. Форма массива — это кортеж, обозначающий размер массива по каждому измерению. Например, массив 2×2 с двумя строками и двумя столбцами имеет форму (2,2). В этом разделе мы узнаем, как использовать некоторые из этих встроенных функций.

Как создать NumPy-массивы

Создание массивов нулей и единиц

Часто полезно создать массив определенных измерений, заполненный всеми нулями или всеми единицами. А затем использовать их и модифицировать на последующих шагах программы.

Мы можем использовать функцию zeros() для создания массива нулей. Передайте форму требуемого массива в виде кортежа: np.zeros(shape) .

 array0 = np.zeros((3,3)) print(array0)

Вот результат, двумерный массив нулей:

 [[0. 0. 0.] [0. 0. 0.] [0. 0. 0.]]

Вы можете получить доступ к атрибутам массива NumPy, вызвать такие атрибуты, как dtype и shape , используя запись через точку, как показано ниже:

 print(array0.dtype) # float64 print(array0.shape) # (3, 3)

Чтобы получить массив единиц, вы можете использовать np.ones() .

 array1 = np.ones((3,3)) print(array1)
 [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]]

Создание матрицы идентичности

Единичная матрица широко используется в нескольких приложениях линейной алгебры. И вы можете использовать np.eye() для создания матрицы идентичности. Функция np.eye() принимает только один аргумент: порядок матрицы ( n ).

 arrayi = np.eye(3) print(arrayi)
 [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]]

Создание массивов случайных чисел

Вы также можете создавать массивы определенной формы, заполненные случайными числами, взятыми из определенных распределений. Обычно используемые распределения вероятностей - это равномерное распределение и стандартное нормальное распределение.

randn() , которая является частью random модуля NumPy, можно использовать для создания массивов чисел, выбранных из стандартного нормального распределения . Стандартное нормальное распределение — это распределение Гаусса с нулевым средним значением и единичной дисперсией.

 std_arr = np.random.randn(3,4) print(std_arr)
 [[-0.13604072 1.21884359 2.06850932 0.78212093] [ 0.44314719 -0.78084801 -0.70517138 1.17984949] [ 1.13214829 1.02339351 0.15317809 1.83191128]]

np.random.rand() возвращает массив выборок чисел из равномерного распределения по интервалу [0,1).

 uniform_arr = np.random.rand(2,3) print(uniform_arr)
 [[0.90470384 0.18877441 0.10021817] [0.741 0.10657658 0.71334643]]

Вы также можете создать массив случайных целых чисел, используя randint() , которая является частью случайного модуля NumPy. np.random.randint(low, high, size) возвращает массив целых чисел. Форма массива выводится из аргумента size , а целые числа принимают значения в интервале [low,high) .

Вот пример:

 int_arr = np.random.randint(1,100,(2,3)) print(int_arr)
 [[53 89 33] [24 85 33]]

Другие полезные встроенные функции

Далее давайте рассмотрим несколько других полезных функций для создания массивов NumPy.

Функция arange() возвращает массив чисел между start и stop значением в шагах значения step : start , start + step , start + 2*step до, но не включая stop . Значения start и step являются необязательными . Размер шага по умолчанию равен 1, а начальное значение по умолчанию равно 0.

В этом примере array_a — это массив чисел, начиная с 1 и заканчивая 10, но не включая 10, с шагом 0,5.

 array_a = np.arange(1,10,0.5) print(array_a)
 [1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5 7. 7.5 8. 8.5 9. 9.5]

Вы также можете создавать массивы равномерно расположенных чисел, используя np.linspace() . Используйте np.linspace(start, stop, num) stop получить массив из num равномерно распределенных чисел между start и конечным значениями.

Здесь arr_lin — это массив из 5 равномерно расположенных чисел в интервале [1,10].

 array_lin = np.linspace(1,10,5) print(array_lin)
 [ 1. 3.25 5.5 7.75 10. ]

Точно так же arr_lin2 представляет собой массив из 10 равномерно расположенных чисел в интервале [1,20].

 array_lin2 = np.linspace(1,20,10) print(array_lin2)
 [ 1. 3.11111111 5.22222222 7.33333333 9.44444444 11.55555556 13.66666667 15.77777778 17.88888889 20. ]

В отличие от функции arange() , функция linspace() включает конечную точку по умолчанию.

Основные операции с массивами NumPy

Далее давайте рассмотрим некоторые основные операции с массивами NumPy.

Нахождение минимального и максимального элементов

Всякий раз, когда мы используем функции из случайного модуля NumPy для создания массивов, мы будем получать разные результаты при каждом запуске кода. Чтобы получить воспроизводимые результаты, мы должны установить начальное значение: np.random.seed(seed_value) .

В следующем примере я установил начальное значение для воспроизводимости, int_arr1 — это массив из семи случайных целых чисел в интервале [1100].

 np.random.seed(27) int_arr1 = np.random.randint(1,100,7) print(int_arr1) # [20 57 73 32 57 38 25]
  • Чтобы найти максимальный элемент в массиве, вы можете вызвать метод max() для объекта массива, int_arr1 и
  • Чтобы найти минимальный элемент в массиве, вы можете вызвать метод min() для объекта массива, int_arr1 .
 int_arr1.max() # 73 int_arr1.min() # 20

Нахождение индекса максимального и минимального элементов

Иногда вам может понадобиться найти индекс максимального и минимального элементов. Для этого вы можете вызвать argmax() и argmin() для объекта массива.

Здесь максимальный элемент 73 находится в индексе 2.

 int_arr1.argmax() # 2

И минимальный элемент 20 находится в индексе 0.

 int_arr1.argmin() # 0

Вы также можете использовать np.argmax(array) и np.argmin(array) , чтобы найти индексы максимального и минимального элементов соответственно. Узнайте больше о функции NumPy argmax() .

Как объединить массивы NumPy

Еще одна распространенная операция, которую вы можете выполнять с массивами NumPy, — это конкатенация.

Вертикальная конкатенация с использованием vstack

Вы можете объединять массивы по вертикали, используя vstack() .

Вот пример. arr1 представляет собой массив из единиц с двумя строками и тремя столбцами, а arr2 представляет собой массив нулей из двух строк и трех столбцов.

 arr1 = np.ones((2,3)) arr2 = np.zeros((2,3))

Мы можем объединить эти два массива по вертикали, используя vstack() , как показано ниже:

 np.vstack((arr1,arr2))
 array([[1., 1., 1.], [1., 1., 1.], [0., 0., 0.], [0., 0., 0.]])

Поскольку наложение происходит вертикально, два массива должны иметь одинаковое количество столбцов .

Давайте изменим arr2 , чтобы он имел форму (2,2). Теперь в нем две строки и два столбца.

 arr1 = np.ones((2,3)) arr2 = np.zeros((2,2)) np.vstack((arr1,arr2))

Следовательно, вертикальная конкатенация невозможна, и мы получаем ValueError.

 --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-21-d5d3bf37fc21> in <module> ----> 1 np.vstack((arr1,arr2)) ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 3 and the array at index 1 has size 2

Горизонтальная конкатенация с использованием hstack

Вы можете объединить массивы NumPy по горизонтали, используя hstack() , как показано ниже.

 arr1 = np.ones((3,3)) arr2 = np.zeros((3,2))
 np.hstack((arr1,arr2))

Поскольку наложение происходит горизонтально, входные массивы должны иметь одинаковое количество строк . Здесь и arr1 , и arr2 имеют по три строки.

 array([[1., 1., 1., 0., 0.], [1., 1., 1., 0., 0.], [1., 1., 1., 0., 0.]])

Использование конкатенации

Вы также можете использовать объединение массивов NumPy вдоль определенной оси с помощью функции concatenate() . Установите необязательный аргумент axis на ось, вдоль которой вы хотите выполнить конкатенацию; значение оси по умолчанию равно нулю.

Вот несколько примеров:

 arr1 = np.ones((2,3)) arr2 = np.zeros((2,3))

Когда мы не указываем ось для конкатенации, массивы объединяются по оси 0. В полученный массив второй массив arr2 добавляется (в виде строк) под первым массивом.

 np.concatenate((arr1,arr2))
 array([[1., 1., 1.], [1., 1., 1.], [0., 0., 0.], [0., 0., 0.]])

Когда мы указываем axis = 1 , мы получаем следующий результат. arr2 объединяется (как столбцы) рядом с первым массивом, arr1 .

 np.concatenate((arr1,arr2),axis=1)
 array([[1., 1., 1., 0., 0., 0.], [1., 1., 1., 0., 0., 0.]])

Как и в случае с hstack() и vstack() , размеры массивов по оси конкатенации должны совпадать .

Заключение

В этом руководстве вы узнали о различиях между массивами NumPy и списками Python, уделив особое внимание преимуществам N-мерных массивов с точки зрения скорости и эффективности.

Вы также изучили несколько полезных функций для создания массивов определенной размерности и выполнения общих операций, таких как поиск минимального и максимального элементов, объединение массивов и многое другое.

Затем узнайте, как изменить массивы NumPy.