Как создавать массивы с равномерно распределёнными значениями
Существует несколько функций NumPy, похожих по применению, но дающих немного разные результаты, что может вызвать путаницу, если не ясно, когда и как их использовать. Следующее руководство призвано перечислить эти функции и описать их рекомендуемое использование.
Функции, упомянутые здесь, это:
Одномерные области (интервалы)
linspace против arange
И numpy.linspace, и numpy.arange предоставляют способы разбиения интервала (одномерной области) на подынтервалы одинаковой длины. Эти разбиения будут различаться в зависимости от выбранных начальной и конечной точек и шага (длины подынтервалов).
-
Используйте
numpy.arange, если вам нужны целочисленные шаги.numpy.arangeопирается на размер шага для определения количества элементов в возвращаемом массиве, исключая конечную точку. Это определяется через аргументstepфункцииarange.Пример:
>>> np.arange(0, 10, 2) # np.arange(start, stop, step) array([0, 2, 4, 6, 8])
Аргументы
startиstopдолжны быть целыми или вещественными, но не комплексными числами.numpy.arangeаналогична встроенной функции Pythonrange.Неточности с плавающей точкой могут сделать результаты
arangeс числами с плавающей точкой непонятными. В этом случае следует использоватьnumpy.linspaceвместо неё. -
Используйте
numpy.linspace, если вы хотите, чтобы конечная точка была включена в результат, или если вы используете размер шага, который не является целым числом.numpy.linspaceможет включать конечную точку и определяет размер шага из аргументаnum, который указывает количество элементов в возвращаемом массиве.Включение конечной точки определяется необязательным булевым аргументом
endpoint, который по умолчанию равенTrue. Обратите внимание, что выборendpoint=Falseизменит вычисление размера шага и последующий вывод функции.Пример:
>>> np.linspace(0.1, 0.2, num=5) # np.linspace(start, stop, num) array([0.1 , 0.125, 0.15 , 0.175, 0.2 ]) >>> np.linspace(0.1, 0.2, num=5, endpoint=False) array([0.1, 0.12, 0.14, 0.16, 0.18])
numpy.linspaceтакже может быть использована с комплексными аргументами:>>> np.linspace(1+1.j, 4, 5, dtype=np.complex64) array([1. +1.j , 1.75+0.75j, 2.5 +0.5j , 3.25+0.25j, 4. +0.j ], dtype=complex64)
Другие примеры
-
Неожиданные результаты могут возникнуть, если значения с плавающей точкой используются в качестве
stepвnumpy.arange. Чтобы этого избежать, убедитесь, что все преобразования чисел с плавающей точкой происходят после вычисления результатов. Например, замените>>> list(np.arange(0.1,0.4,0.1).round(1)) [0.1, 0.2, 0.3, 0.4] # endpoint should not be included!
на
>>> list(np.arange(1, 4, 1) / 10.0) [0.1, 0.2, 0.3] # expected result
-
Обратите внимание, что
>>> np.arange(0, 1.12, 0.04) array([0. , 0.04, 0.08, 0.12, 0.16, 0.2 , 0.24, 0.28, 0.32, 0.36, 0.4 , 0.44, 0.48, 0.52, 0.56, 0.6 , 0.64, 0.68, 0.72, 0.76, 0.8 , 0.84, 0.88, 0.92, 0.96, 1. , 1.04, 1.08, 1.12])и
>>> np.arange(0, 1.08, 0.04) array([0. , 0.04, 0.08, 0.12, 0.16, 0.2 , 0.24, 0.28, 0.32, 0.36, 0.4 , 0.44, 0.48, 0.52, 0.56, 0.6 , 0.64, 0.68, 0.72, 0.76, 0.8 , 0.84, 0.88, 0.92, 0.96, 1. , 1.04])Они различаются из-за численного шума. При использовании значений с плавающей точкой возможно, что
0 + 0.04 * 28 < 1.12, и поэтому1.12попадает в интервал. На самом деле, это именно тот случай:>>> 1.12/0.04 28.000000000000004
Но
0 + 0.04 * 27 >= 1.08, так что 1.08 исключается:>>> 1.08/0.04 27.0
В качестве альтернативы, вы можете использовать
np.arange(0, 28)*0.04, что всегда даст вам точный контроль над конечной точкой, поскольку она целочисленная:>>> np.arange(0, 28)*0.04 array([0. , 0.04, 0.08, 0.12, 0.16, 0.2 , 0.24, 0.28, 0.32, 0.36, 0.4 , 0.44, 0.48, 0.52, 0.56, 0.6 , 0.64, 0.68, 0.72, 0.76, 0.8 , 0.84, 0.88, 0.92, 0.96, 1. , 1.04, 1.08])
geomspace и logspace
numpy.geomspace аналогична numpy.linspace, но с числами, равномерно распределенными на логарифмической шкале (геометрическая прогрессия). Конечная точка включена в результат.
Пример:
>>> np.geomspace(2, 3, num=5) array([2. , 2.21336384, 2.44948974, 2.71080601, 3. ])
numpy.logspace аналогична numpy.geomspace, но начальная и конечная точки задаются как логарифмы (по умолчанию основание 10):
>>> np.logspace(2, 3, num=5) array([ 100. , 177.827941 , 316.22776602, 562.34132519, 1000. ])
В линейном масштабе последовательность начинается с base ** start (base в степени start) и заканчивается base ** stop:
>>> np.logspace(2, 3, num=5, base=2) array([4. , 4.75682846, 5.65685425, 6.72717132, 8. ])
N-мерные области
N-мерные области могут быть разбиты на сетки. Это можно сделать, используя одну из следующих функций.
meshgrid
Цель numpy.meshgrid — создание прямоугольной сетки из набора одномерных координатных массивов.
Даны массивы:
>>> x = np.array([0, 1, 2, 3]) >>> y = np.array([0, 1, 2, 3, 4, 5])
meshgrid создаст два координатных массива, которые можно использовать для генерации пар координат, определяющих эту сетку.:
>>> xx, yy = np.meshgrid(x, y)
>>> xx
array([[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]])
>>> yy
array([[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3],
[4, 4, 4, 4],
[5, 5, 5, 5]])
>>> import matplotlib.pyplot as plt
>>> plt.plot(xx, yy, marker='.', color='k', linestyle='none')
mgrid
numpy.mgrid может использоваться как сокращение для создания сетки. Это не функция, но при индексировании возвращает многомерную сетку.
>>> xx, yy = np.meshgrid(np.array([0, 1, 2, 3]), np.array([0, 1, 2, 3, 4, 5]))
>>> xx.T, yy.T
(array([[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3]]),
array([[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]]))
>>> np.mgrid[0:4, 0:6]
array([[[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3]],
[[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5]]])
ogrid
Аналогично numpy.mgrid, numpy.ogrid возвращает открытую многомерную сетку. Это означает, что при индексировании только одно измерение каждого возвращаемого массива больше 1. Это позволяет избежать повторения данных и, таким образом, экономит память, что часто желательно.
Эти разреженные координатные сетки предназначены для использования с векторизацией. При использовании всех координат в выражении векторизация по-прежнему приводит к массиву результатов с полными измерениями.
>>> np.ogrid[0:4, 0:6]
[array([[0],
[1],
[2],
[3]]), array([[0, 1, 2, 3, 4, 5]])]
Все три описанных здесь метода могут быть использованы для вычисления значений функции на сетке.
>>> g = np.ogrid[0:4, 0:6] >>> zg = np.sqrt(g[0]**2 + g[1]**2) >>> g[0].shape, g[1].shape, zg.shape ((4, 1), (1, 6), (4, 6)) >>> m = np.mgrid[0:4, 0:6] >>> zm = np.sqrt(m[0]**2 + m[1]**2) >>> np.array_equal(zm, zg) True
© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/user/how-to-partition.html