|
Функции автозаполнения, создания матриц и числовых диапазонов
На предыдущем
занятии мы познакомились с функцией array для создания
произвольных массивов на основе переданного ей списка или кортежа. Однако,
часто в инженерных задачах требуется определять векторы или матрицы с типовым
набором значений, например, состоящих из нулей или единиц, или определение
диагональной и единичной матриц и так далее. Конечно, мы можем все это сделать
также через функцию array, используя механизм генерации списков,
например, так:
np.array( [0]*10 ) # массив из 10 нулей
np.array( [1]*15 ) # массив из 15 единиц
np.array( [x for x in range(10)] ) # массив из чисел от 0 до 9
Но есть более
быстрые способы (по скорости выполнения) создания подобных массивов. Для этого
в NumPyимеются полезные
функции, которые мы сейчас рассмотрим.
Функции автозаполнения элементов массива
Название
|
Описание
|
empty(shape, …)
|
Возвращает
новый массив заданного размера и типа данных, но без определенных значений.
|
eye(N,
M=None,
…)
|
Возвращает
массив размером NxMс единичными диагональными элементами
(остальные элементы равны нулю).
|
identity(n,
…)
|
Возвращает
квадратный массив размерностью nxn с единичными элементами по главной
диагонали (остальные равны нулю).
|
ones(shape, …)
|
Возвращает
массив заданного размера и типа, состоящего из всех единиц.
|
zeros(shape, …)
|
Возвращает
массив заданного размера и типа, состоящего из всех нулей.
|
full(shape,
value,
…)
|
Возвращает
массив заданного размера и типа со значениями value.
|
Это только часть
основных функций для создания массивов с заданными значениями. Использовать их
достаточно просто. Например, так:
np.empty(10) # создание одномерного массива с произвольными числами
np.empty(10, dtype='int16')
np.empty((3, 2), dtype='float32') # возвращаетматрицу 3x2 стипомfloat32
Для функций eye и identity
размерности указываются отдельными параметрами:
np.eye(4) # матрица 4х4
np.eye(4, 2) # матрица 4x2
np.identity(5) # матрица 5x5
Функции ones, zeros
и full работают по аналогии с функцией empty:
np.zeros( (2, 3, 4) ) # нулевая матрица размерностью 2x3x4
np.ones( [4, 3], dtype='int8') # матрица 4x3 из единиц и типом int8
np.full((3, 2), -1) # матрица 3x2, состоящая из -1
Все эти функции
работают быстрее, чем функция array с генератором списков языка Python. Поэтому их
предпочтительно использовать при создании и инициализации массивов
определенными значениями.
Функции создания матриц
Следующий
полезный набор функций позволяет генерировать матрицы на основе списков или по
определенным правилам.
Название
|
Описание
|
mat(object,
…)
|
Приводит
входные данные object к матрице, если это возможно. Параметр
object может быть
строкой, списком или кортежем.
|
diag(list, …)
|
Формирует
диагональную матрицу на основе списка или массива NumPy. В последних
версиях возвращает копию массива (а не его представление).
|
diagflat(list,
…)
|
Формирует
диагональную матрицу из списка list, который сначала сжимает до
одной оси (преобразует в одномерный список или массив).
|
tri(N,
M=None, …)
|
Создает
треугольный массив NxM с единицами на главной диагонали и
ниже ее.
|
tril(list,
…)
|
Преобразует
двумерный список или массив list в треугольную матрицу с
нулевыми элементами выше главной диагонали.
|
triu(list,
…)
|
Преобразует
двумерный список или массив list в треугольную матрицу с
нулевыми элементами ниже главной диагонали.
|
vander(list,
N=None, …)
|
Создание
матрицы Вандермонда из одномерного списка или массива list. Второй
параметр N определяет
число столбцов (по умолчанию формируется квадратная матрица).
|
Давайте
посмотрим как работают эти функции.
np.mat('1 2 3 4') # создает матрицу 1x4 из строки
np.mat('1, 2, 3, 4') # то же самое: создает матрицу 1x4 из строки
np.mat('1 2; 3 4') # возвращает матрицу 2x2
Или же, вместо
строк можно использовать список или кортеж:
np.mat([5, 4, 3])
np.mat( [(1,2,3), (4,5,6)])
Но, если из
переданных данных нельзя сформировать прямоугольную таблицу (матрицу), то
произойдет ошибка:
np.mat( [(1,2,3), (4,5,6,7)])# ошибка, размерности не совпадают
Следующая функция
позволяет формировать диагональные матрицы:
np.diag([1, 2, 3]) # диагональная матрица 3x3
Но, если ей
передать двумерный список, то она возвратит одномерный массив из элементов,
стоящих на главной диагонали:
np.diag([(1,2,3), (4,5,6), (7,8,9)]) # выделение элементов главной диагонали
Если же мы хотим
сформировать диагональную матрицу из многомерных списков или массивов, то
следует воспользоваться функцией
np.diagflat([(1,2,3), (4,5,6), (7,8,9)])
Следующий набор
функций используются для формирования треугольных матриц. Например:
np.tri(4) # треугольная матрица 4x4
np.tri(4, 2) # треугольная матрица 4x2
Если нужно
привести уже существующие матрицы к треугольному виду, то это можно сделать
так:
a = np.array( [(1,2,3), (4,5,6), (7,8,9)] )
np.tril(a) # нижняя треугольная матрица размером 3x3
np.triu(a) # верхняя треугольная матрица размером 3x3
Если указать
одномерный список:
то будет создана
треугольная матрица 3x3 из строк [1, 2, 3].
Также функции tril
и triu будут работать
и с многомерными массивами:
np.tril([[[1,2,3], [4,5,6], [7,8,9]]])
np.tril([[[1,2,3], [4,5,6], [7,8,9]], [[10,20,30], [40,50,60], [70,80,90]], [[100,200,300], [400,500,600], [700,800,900]]])
В этом случае
последние двумерные сечения будут приведены к треугольному виду.
Последняя
функция этойгруппы формирует матрицу Вандермонда из одномерных списков или
массивов:
np.vander([1,2,3]) # матрица Вандермонда 3x3
Функции формирования числовых диапазонов
Следующая группа
функций, которые мы рассмотрим на этом занятии, служит для формирования
числовых диапазонов. Что делают эти функции? Когда мы с вами изучали язык Python, то говорили о
функции
range(Start, Stop, Step)
которая
генерирует числовой диапазон с параметрами Start, Stop, Step. Причем, все
эти параметры должны быть целочисленными. В NumPy есть подобные
функции, но более гибкие и работающие с вещественными величинами.
Название
|
Описание
|
arange()
|
Возвращает
одномерный массив с равномерно разнесенными числами указанного диапазона.
|
linspace(start,
stop, …)
|
Возвращает
одномерный массивcравномерно разнесенными числами, используя только
значения начала и конца интервала.
|
logspace(start,
stop, …)
|
Возвращает
одномерный массив с числами, равномерно распределенных по логарифмической
шкале.
|
geomspace(start,
stop, …)
|
Формирование
чисел по геометрической прогрессии.
|
meshgrid(x1,
..., xn, …)
|
x1,
..., xn – одномерные последовательности или массивы, используемые для
формирования координатной сетки по каждой из осей.
|
mgrid[]
|
Возвращает
массив плотных координатных сеток.
|
ogrid[]
|
Возвращает
открытую сетку значений.
|
Давайте
рассмотрим некоторые из них. Первая функция arrange довольно часто
применяется в программах на Python. Она позволяет проходить
заданный интервал с указанным шагом, например, так:
np.arange(5)# интервал [0; 5) с шагом 1
np.arange(1, 5)# интервал [1; 5) с шагом 1
np.arange(1, 5, 0.5) # интервал [1; 5) с шагом 0,5
Обратите
внимание, в отличие от функции range языка Python в arrange пакета NumPy можно указывать
вещественные значения. Вот еще один пример, демонстрирующий это:
Здесь все
величины вещественные. Мы начинаем движение от значения 0 с шагом 0,1 пока не
дойдем до значения пи (не включая его). И, далее, используя этот массив, можно
вычислить синус или косинус от всех этих значений:
np.cos(np.arange(0, np.pi, 0.1))
Видите, как это
удобно. Без пакета NumPyнам пришлось бы писать цикл и делать
вычисление для каждого значения аргумента. А здесь мы сразу получаем готовый
массив значений функции косинуса. Это работает гораздо быстрее циклов в Python.
Похожим образом
работает и функция linspace. Она разбивает указанный интервал на равномерные
отрезки и возвращает массив этих значений:
Мы указываем в
качестве аргументов интервал [start; stop] и число
отметок в этом интервале n. Если n = 0, то получим
пустой массив. При n = 1 – значение start. При n = 2 – значения start и stop. При n> 2
равномерное разбиение интервала точками m = n-2. Например:
np.linspace(0, np.pi, 0) # пустой массив
np.linspace(0, np.pi, 1) # одно значение 0
np.linspace(0, np.pi, 2) # два значения: 0 и pi
np.linspace(0, np.pi, 3) # три значения: 0, pi/2, pi
В чем отличие linspace от arange? В arange мы указываем
сами шаг движения по числовой оси. При этом число значений определяется
граничными значениями. А в linspace мы задаем граничные значения и
число делений, а шаг вычисляется автоматически.
Функции logspace
и geomspace работают аналогичным образом. У них указываются граничные значения
и число членов, а на выходе имеем массив из соответствующих величин. Например:
np.logspace(0, 1, 3) # значения: 1, sqrt(10), 10
np.logspace(0, 1, 4) # значения: 1, 2.15, 4.64, 10
np.geomspace(1, 4, 3) # значения: 1, 2, 4
np.geomspace(1, 16, 5) # значения: 1, 2, 4, 8, 16
Остальные
функции этой группы используются при построении графиков и мы их рассмотрим,
когда будем рассматривать построение графиков с помощью библиотеки matplotlib.
Функции формирования массивов на основе данных
Рассмотрим
следующую группу, связанную с формированием на основе уже имеющихся данных.
Название
|
Описание
|
array(object,
…)
|
Преобразует
список или кортеж object в массив NumPy.
|
asanyarray(list,
…)
|
Преобразует
список list в массив array, сохраняя тип
подкласса.
|
ascontiguousarray(list,
…)
|
Возвращает
непрерывный массив в памяти, подобно как это организовано в языке C.
|
asmatrix(list,
…)
|
Преобразует
входную последовательность list в матрицу NumPy (тип matrix).
|
copy(list,
…)
|
Возвращает
копию массива list (если это объект NumPy) или просто
создает массив на основе списка языка Python.
|
frombuffer(buffer,
…)
|
Преобразует
данные из буфера в массив NumPy
|
fromfile(file,
…)
|
Возвращает
массив из данных текстового или бинарного файла file.
|
fromfunction(func,
shape, …)
|
Создает
массивразмерностью shape с помощью функции func.
|
fromiter(iter,
…)
|
Создает
массив на основе итерируемого объекта.
|
fromstring(string,
…)
|
Создает
массив из данных строки.
|
loadtxt(file,
…)
|
Формирует
массив из данных текстового файла.
|
Работа этих
функций вполне очевидна, рассмотрим только некоторые из них. Функция copy выполняет
копирование массива. Например, имеется массив:
a = np.array( [(1, 2), (3, 4)] )
И создать его
копию в памяти устройства, можно так:
В этом легко
убедиться, если вывести id этих объектов:
Формирование
массива с помощью функции выполняется следующим образом:
def getRange(x, y):
return 100*x + y
a = np.fromfunction(getRange, (2, 2))
print(a)
Обратите
внимание, функция принимает два аргумента, т.к. формируется двумерная матрица
размерами 2x2. То есть,
число аргументов функции равно размерности матрицы и каждый аргумент
соответствует индексу по своей оси. При выполнении этой программы в консоли
увидим результат:
[[
0. 1.]
[100. 101.]]
Отсюда хорошо
видно как менялись значения x, y при
формировании матрицы. При формировании первой строки x = 0, а yменялся от 0 до
1, при формировании второй строки: x = 1, yот 0 до 1.
Часто совместно
с fromfunction используют лямбда-функции в виде:
np.fromfunction(lambda x, y: x*100+y, (2, 2))
Результат будет
тем же.
Следующая
функция fromiter позволяет формировать массив на основе любого итерируемого
объекта. Например:
np.fromiter("hello", dtype='U1')
Здесь строка
воспринимается как итерируемый объект и разбивается по символам. Или, можносделатьтак:
def getRange(N):
for i in range(N):
yield i
a = np.fromiter(getRange(4), dtype='int8')
print(a)
Здесь в качестве
объекта передается функция-генератор и на выходе получаем одномерный массив
чисел:
[0 1 2 3]
Последняя
функция, которую мы рассмотрим fromstring позволяет создавать массив из
строковых данных, например, так:
np.fromstring('1 2 3', dtype='int16', sep= ' ')
Здесь параметр sep определяет
разделитель между данными. Если числа следуют через запятую, то это явно нужно
указать в разделителе:
np.fromstring('1, 2, 3', dtype='int16', sep= ',')
Это
не все функции, с помощью которых можно формировать массивы в NumPy. Я отметил лишь
наиболее употребительные. Полный их список и подробное описание можно
посмотреть на официальном сайте:
https://numpy.org/doc/stable/
|