NumPy arange(): Как использовать np.arange()
Оглавление
- Возвращаемое значение и параметры np.arange()
- Аргументы диапазона np.arange()
- Типы данных np.arange()
- За пределами простых диапазонов с помощью np.arange()
- Сравнение диапазона и np.arange()
- Другие процедуры, основанные на числовых диапазонах
- Краткое резюме
- Заключение
NumPy - это фундаментальная библиотека Python для численных вычислений. Его наиболее важным типом является тип массива, называемый ndarray
. NumPy предлагает множество процедур создания массивов для различных случаев. arange()
- это одна из таких функций, основанная на числовых диапазонах. Его часто называют np.arange()
, потому что np
- это широко используемая аббревиатура от NumPy.
Создание массивов NumPy важно, когда вы работаете с другими библиотеками Python, которые полагаются на них, такими как SciPy, Pandas, Matplotlib, scikit-learn и многое другое. NumPy подходит для создания массивов и работы с ними, поскольку он предлагает полезных процедур, позволяет повысить производительность и позволяет писать лаконично код.
К концу этой статьи вы будете знать:
- Что такое
np.arange()
- Как использовать
np.arange()
- Как
np.arange()
сравнивается со встроенным классом Pythonrange
- Какие процедуры похожи на
np.arange()
Давайте посмотрим на np.arange()
в действии!
Возвращаемое значение и параметры np.arange()
NumPy arange()
- это одна из процедур создания массивов, основанная на числовых диапазонах. Он создает экземпляр ndarray
с равномерно распределенными значениями и возвращает ссылку на него.
Вы можете определить интервал значений, содержащихся в массиве, расстояние между ними и их тип с помощью четырех параметров arange()
:
numpy.arange([start, ]stop, [step, ], dtype=None) -> numpy.ndarray
Первые три параметра определяют диапазон значений, в то время как четвертый определяет тип элементов:
start
это число (целое или десятичное), которое определяет первое значение в массиве.stop
это число, которое определяет конец массива и не входит в него.step
это число, которое определяет интервал (разницу) между каждыми двумя последовательными значениями в массиве и по умолчанию равно1
.dtype
является типом элементов выходного массива и по умолчанию имеет значениеNone
.
step
не может быть равно нулю. В противном случае вы получите ZeroDivisionError
. Вы не можете никуда отойти от start
, если увеличение или уменьшение 0
.
Если dtype
не указано, arange()
попытается определить тип элементов массива из типов start
, stop
, и step
.
Вы можете найти более подробную информацию о параметрах и возвращаемом значении arange()
в официальной документации .
Диапазон аргументов np.arange()
Аргументы NumPy arange()
, которые определяют значения, содержащиеся в массиве, соответствуют числовым параметрам start
, stop
, и step
. Вы должны пройти хотя бы один из них.
Следующие примеры покажут вам, как ведет себя arange()
в зависимости от количества аргументов и их значений.
Предоставление всех аргументов диапазона
При работе с подпрограммами NumPy сначала необходимо импортировать NumPy:
>>> import numpy as np
Теперь вы импортировали NumPy и готовы к применению arange()
.
Давайте посмотрим первый пример использования NumPy arange()
:
>>> np.arange(start=1, stop=10, step=3)
array([1, 4, 7])
В этом примере start
равно 1
. Следовательно, первый элемент полученного массива 1
. step
равен 3
, поэтому ваше второе значение равно 1+3, то есть 4
, в то время как третье значение в массиве равно 4+3, что равно 7
.
В соответствии с этим шаблоном следующим значением будет 10
(7+3),, но подсчет должен быть завершен до достижения значения stop
, поэтому это значение не включено.
Вы также можете передать start
, stop
, и step
в качестве позиционных аргументов:
>>> np.arange(1, 10, 3)
array([1, 4, 7])
Этот пример кода эквивалентен предыдущему, но более лаконичен.
Значение stop
не включено в массив. Вот почему вы можете получить идентичные результаты с разными значениями stop
:
>>> np.arange(1, 8, 3)
array([1, 4, 7])
Этот пример кода возвращает массив с теми же значениями, что и в предыдущих двух. Вы можете получить тот же результат при любом значении stop
, строго большем, чем 7
, и меньшем или равном 10
.
Однако, если вы сделаете stop
больше, чем 10
, то подсчет завершится после достижения 10
:
>>> np.arange(1, 10.1, 3)
array([ 1., 4., 7., 10.])
В этом случае вы получаете массив из четырех элементов, который включает 10
.
Обратите внимание, что в этом примере, в отличие от предыдущего, создается массив чисел с плавающей запятой. Это потому, что вы не определили dtype
, а arange()
вывел это за вас. Вы узнаете больше об этом позже в статье.
Вы можете увидеть графическое представление этих трех примеров на рисунке ниже:
start
отображается зеленым цветом, stop
- красным, в то время как step
и значения, содержащиеся в массивах, выделены синим цветом.
Как вы можете видеть из рисунка выше, в первых двух примерах учитываются три значения (1
, 4
, и 7
). Они не позволяют включать 10
. В третьем примере значение stop
больше, чем 10
, и оно содержится в результирующем массиве.
Предоставление двух аргументов диапазона
Вы можете опустить step
. В этом случае для arange()
используется значение по умолчанию 1
. Следующие два утверждения эквивалентны:
>>> np.arange(start=1, stop=10, step=1)
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(start=1, stop=10)
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
Второе утверждение короче. step
, значение которого по умолчанию равно 1
, - это то, что обычно интуитивно ожидается.
Использование arange()
с шагом 1
является очень распространенным случаем на практике. Опять же, вы можете написать предыдущий пример более кратко, используя позиционные аргументы start
и stop
:
>>> np.arange(1, 10)
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
Это интуитивно понятный и лаконичный способ вызова arange()
. Использование ключевых слов arguments в этом примере на самом деле не улучшает читаемость.
Примечание: Если вы указываете два позиционных аргумента, то первый из них равен start
, а второй stop
.
Предоставление одного аргумента диапазона
Вы должны предоставить хотя бы один аргумент в пользу arange()
. Чтобы быть более точным, вы должны предоставить start
.
Но что произойдет, если вы опустите stop
? Откуда arange()
знает, когда нужно прекратить подсчет? В этом случае массив начинается с 0
и заканчивается до достижения значения start
! Опять же, значение по умолчанию step
равно 1
.
Другими словами, arange()
предполагает, что вы указали stop
(вместо start
) и что start
равно 0
и step
есть 1
.
Давайте рассмотрим пример, в котором вы хотите начать массив с 0
, увеличив значения на 1
, и остановиться перед 10
:
>>> np.arange(start=0, stop=10, step=1)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(0, 10, 1)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(start=0, stop=10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.arange(0, 10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
С этими примерами кода все в порядке. Они работают так, как показано в предыдущих примерах. Есть еще более короткий и понятный, но все же интуитивно понятный способ сделать то же самое. Вы можете просто указать один позиционный аргумент:
>>> np.arange(10) # Stop is 10, start is 0, and step is 1!
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Это самый обычный способ создания массива NumPy, который начинается с нуля и имеет приращение, равное единице.
Примечание: Единственный аргумент определяет, где заканчивается подсчет. Выходной массив начинается с 0
и имеет приращение 1
.
Если вы попытаетесь явно указать stop
без start
, то получите TypeError
:
>>> np.arange(stop=10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: arange() missing required argument 'start' (pos 1)
Вы получили сообщение об ошибке, потому что arange()
не позволяет вам явно избегать первого аргумента, который соответствует start
. Если вы указываете один аргумент, то он должен быть start
, но arange()
будет использовать его для определения того, где заканчивается подсчет.
Предоставление отрицательных аргументов
Если вы указали отрицательные значения для start
или для обоих start
и stop
, а также положительное step
, то arange()
будет работать точно так же, как и со всеми положительными аргументами:
>>> np.arange(-5, -1)
array([-5, -4, -3, -2])
>>> np.arange(-8, -2, 2)
array([-8, -6, -4])
>>> np.arange(-5, 6, 4)
array([-5, -1, 3])
Такое поведение полностью соответствует предыдущим примерам. Подсчет начинается со значения start
, многократно увеличивается на step
и заканчивается до достижения stop
.
Обратный отсчет
Иногда вам может понадобиться массив со значениями, уменьшающимися слева направо. В таких случаях вы можете использовать arange()
с отрицательным значением для step
и с значением start
, превышающим stop
:
>>> np.arange(5, 1, -1)
array([5, 4, 3, 2])
>>> np.arange(7, 0, -3)
array([7, 4, 1])
В этом примере обратите внимание на следующую закономерность: полученный массив начинается со значения первого аргумента и уменьшается для step
до значения второго аргумента.
В последнем операторе start
равно 7
, и результирующий массив начинается с этого значения. step
равно -3
таким образом, второе значение равно 7+(-3), то есть 4
. Третье значение равно 4+(-3), или 1
. Здесь отсчет прекращается, так как stop
(0
) достигается до следующего значения (-2
).
Вы можете увидеть графическое представление этого примера на рисунке ниже:
Опять же, start
отображается зеленым цветом, stop
- красным, в то время как step
и значения, содержащиеся в массиве, выделены синим цветом.
На этот раз стрелки показывают направление справа налево. Это потому, что start
больше, чем stop
, step
равно отрицательному значению, и вы, по сути, ведете обратный отсчет.
Предыдущий пример дает тот же результат, что и следующий:
>>> np.arange(1, 8, 3)[::-1]
array([7, 4, 1])
>>> np.flip(np.arange(1, 8, 3))
array([7, 4, 1])
Однако вариант с отрицательным значением step
является более элегантным и лаконичным.
Получение пустых массивов
Существует несколько крайних случаев, когда вы можете получить пустые массивы NumPy с помощью arange()
. Это обычные экземпляры numpy.ndarray
без каких-либо элементов.
Если вы укажете одинаковые значения для start
и stop
, то получите пустой массив:
>>> np.arange(2, 2)
array([], dtype=int64)
Это происходит потому, что подсчет заканчивается до достижения значения stop
. Поскольку значение start
равно stop
, оно также не может быть получено и включено в результирующий массив.
Один из необычных случаев - это когда start
больше, чем stop
, а step
положительное значение, или когда start
меньше, чем stop
и step
отрицательное значение:
>>> np.arange(8, 2, 1)
array([], dtype=int64)
>>> np.arange(2, 8, -1)
array([], dtype=int64)
Как вы можете видеть, в результате этих примеров получаются пустые массивы, а не с ошибками.
Типы данных np.arange()
Типы элементов в массивах NumPy являются важным аспектом их использования. При работе с arange()
вы можете указать тип элементов с помощью параметра dtype
.
Примечание: Вот несколько важных замечаний о типах элементов, содержащихся в массивах NumPy:
- Все элементы в массиве NumPy имеют один и тот же тип, называемый dtype (сокращение от тип данных).
- Типы NumPy обеспечивают большую степень детализации, чем встроенные числовые типы Python.
- В некоторых случаях типы NumPy dtypes имеют псевдонимы, соответствующие именам встроенных типов Python.
- Обычно подпрограммы NumPy могут принимать числовые типы Python и наоборот.
- Некоторые dtypes NumPy имеют определения, зависящие от платформы.
Если вы хотите узнать больше о типах массивов NumPy, пожалуйста, ознакомьтесь с официальной документацией .
Вы можете опустить dtype
. В этом случае arange()
попытается определить тип результирующего массива. Это зависит от типов start
, stop
, и step
, как вы можете видеть в следующем примере:
>>> x = np.arange(5)
>>> x
array([0, 1, 2, 3, 4])
>>> x.dtype
dtype('int64')
>>> x.itemsize # In bytes
8
Здесь есть один аргумент (5
), который определяет диапазон значений. Его тип - int
. Вот почему dtype массива x
будет одним из целочисленных типов, предоставляемых NumPy. В этом случае NumPy по умолчанию выбирает тип int64
d. Это 64-разрядный (8-байтовый) целочисленный тип.
Массив в предыдущем примере эквивалентен этому:
>>> x = np.arange(5, dtype=int)
>>> x
array([0, 1, 2, 3, 4])
>>> x.dtype
dtype('int64')
Аргумент dtype=int
не относится к Python int
. Это переводится как NumPy int64
или просто np.int
.
NumPy предлагает вам несколько целочисленных типов с фиксированным размером, которые отличаются объемом памяти и ограничениями:
np.int8
: 8- разрядное целое число со знаком (от-128
до127
)np.uint8
: 8- разрядное целое число без знака (от0
до255
)np.int16
: 16- разрядное целое число со знаком (от-32768
до32767
)np.uint16
: 16- разрядное целое число без знака (от0
до65535
)np.int32
: 32- разрядное целое число со знаком (от-2**31
до2**31-1
)np.uint32
: 32- разрядное целое число без знака (от0
до2**32-1
)np.int64
: 64- разрядное целое число со знаком (от-2**63
до2**63-1
)np.uint64
: 64- разрядное целое число без знака (от0
до2**64-1
)
Если вам нужны другие целочисленные типы для элементов вашего массива, то просто укажите dtype
:
>>> x = np.arange(5, dtype=np.int32)
>>> x
array([0, 1, 2, 3, 4], dtype=int32)
>>> x.dtype
dtype('int32')
>>> x.itemsize # In bytes
4
Теперь результирующий массив имеет те же значения, что и в предыдущем случае, но типы и размеры элементов отличаются. Аргумент dtype=np.int32
(или dtype='int32'
) определяет размер каждого элемента x
равным 32 битам (4 байтам).
Если вашим аргументом является десятичное число, а не целое, то в данном случае типом будет какой-нибудь числовой тип с плавающей запятой float64
:
>>> y = np.arange(5.0)
>>> y
array([0., 1., 2., 3., 4.])
>>> y.dtype
dtype('float64')
Значения элементов в последних четырех примерах одинаковы, но типы различаются.
Как правило, когда вы указываете хотя бы один аргумент с плавающей запятой в arange()
, результирующий массив будет содержать элементы с плавающей запятой, даже если другие аргументы являются целыми числами:
>>> np.arange(1, 5.1)
array([1., 2., 3., 4., 5.])
>>> np.arange(1, 5.1).dtype
dtype('float64')
>>> np.arange(0, 9, 1.5)
array([0. , 1.5, 3. , 4.5, 6. , 7.5])
>>> np.arange(0, 9, 1.5).dtype
dtype('float64')
В приведенных выше примерах start
является целым числом, но тип np.float64
, поскольку stop
или step
являются числами с плавающей запятой.
Если вы укажете dtype
, то arange()
попытается создать массив с элементами указанного типа данных:
>>> y = np.arange(5, dtype=float)
>>> y
array([0., 1., 2., 3., 4.])
>>> y.dtype
dtype('float64')
Аргумент dtype=float
здесь переводится как NumPy float64
, то есть np.float
. Это не относится к Python float
. Псевдонимами фиксированного размера для float64
являются np.float64
и np.float_
.
Если вам нужен тип с плавающей запятой с меньшей точностью и размером (в байтах), вы можете явно указать, что:
>>> z = np.arange(5, dtype=np.float32)
>>> z
array([0., 1., 2., 3., 4.], dtype=float32)
>>> z.dtype
dtype('float32')
При использовании dtype=np.float32
(или dtype='float32'
) размер каждого элемента массива z
составляет 32 бита (4 байта). Размер каждого элемента y
равен 64 битам (8 байтам):
>>> y.itemsize # In bytes
8
>>> z.itemsize # In bytes
4
Разница между элементами y
и z
, и, как правило, между np.float64
и np.float32
заключается в используемой памяти и точности: первый больше и более точный, чем последний.
Во многих случаях вы не заметите этой разницы. Однако иногда это важно. Например, TensorFlow использует float32
и int32
. Аналогично, когда вы работаете с изображениями, используются даже более мелкие типы, такие как uint8
.
Если step
не является целым числом, результаты могут быть противоречивыми из-за ограничений арифметики с плавающей запятой.
За пределами простых диапазонов С np.arange()
Вы можете удобно комбинировать arange()
с операторами (например, +
, -
, *
, /
, **
и т.д.) и другими подпрограммами NumPy (например, abs()
или sin()
) для получения диапазонов выходных значений :
>>> x = np.arange(5)
>>> x
array([0, 1, 2, 3, 4])
>>> 2**x
array([ 1, 2, 4, 8, 16])
>>> y = np.arange(-1, 1.1, 0.5)
>>> y
array([-1. , -0.5, 0. , 0.5, 1. ])
>>> np.abs(y)
array([1. , 0.5, 0. , 0.5, 1. ])
>>> z = np.arange(10)
>>> np.sin(z)
array([ 0. , 0.84147098, 0.90929743, 0.14112001, -0.7568025 ,
-0.95892427, -0.2794155 , 0.6569866 , 0.98935825, 0.41211849])
Это особенно удобно, когда вы хотите создать график в Matplotlib.
Если вам нужен многомерный массив, то вы можете комбинировать arange()
с .reshape()
или аналогичными функциями и методами:
>>> a = np.arange(6).reshape((2, 3))
>>> a
array([[0, 1, 2],
[3, 4, 5]])
>>> a.shape
(2, 3)
>>> a.ndim
2
Вот как вы можете получить экземпляр ndarray
с элементами [0, 1, 2, 3, 4, 5]
и преобразовать в двумерный массив.
Сравнение range
и np.arange()
В Python есть встроенный класс range
, в некоторой степени похожий на NumPy arange()
. range
и np.arange()
имеют важные различия, связанные с применением и производительностью. Вы увидите их различия и сходства.
Основное различие между ними заключается в том, что range
- это встроенный класс Python, в то время как arange()
- это функция, принадлежащая третьему классу.-партийная библиотека (NumPy).
Кроме того, у них разные цели! Как правило, range
больше подходит, когда вам нужно выполнить итерацию, используя цикл Python for
. Если вы хотите создать массив NumPy и применить быстрые циклы, то arange()
- это гораздо лучшее решение.
Параметры и выходные данные
И range
, и arange()
имеют одинаковые параметры, которые определяют диапазоны полученных чисел:
start
stop
step
Вы применяете эти параметры аналогично, даже в тех случаях, когда start
и stop
равны.
Однако при работе с range
:
- Вы должны указать целочисленные аргументы. В противном случае вы получите
TypeError
. - Вы не можете указать тип получаемых чисел. Это всегда
int
.
range
и arange()
также различаются типами возвращаемых значений:
range
создает экземпляр этого класса, который обладает теми же функциями, что и другие последовательности (например,list
иtuple
),, такие как членство, объединение, повторение, нарезка, сравнение, проверка длины и другие).arange()
возвращает экземпляр NumPyndarray
.
Создание последовательностей
Вы можете применить range
для создания экземпляра list
или tuple
с равномерно расположенными числами в пределах заданного диапазона. Возможно, вы найдете описания особенно подходящими для этой цели.
Однако создание массивов NumPy и манипулирование ими часто быстрее и более элегантно, чем работа со списками или кортежами.
Давайте сравним производительность создания list
с использованием понимания с эквивалентным NumPy ndarray
с arange()
:
>>> import timeit
>>> n = 1
>>> timeit.timeit(f'x = [i**2 for i in range({n})]')
>>> timeit.timeit(f'x = np.arange({n})**2', setup='import numpy as np')
Повторение этого кода для различных значений n
дало следующие результаты на моем компьютере:
Size: n |
Time Per Loop: range |
Time Per Loop: arange() |
Ratio |
---|---|---|---|
1 | 497 ns | 1.14 µs | 0.41 |
10 | 2.24 µs | 1.28 µs | 1.74 |
100 | 20.0 µs | 1.37 µs | 14.6 |
1,000 | 211 µs | 2.92 µs | 72.3 |
Эти результаты могут отличаться, но очевидно, что вы можете создать массив NumPy намного быстрее, чем список, за исключением последовательностей очень малой длины. (Это приложение часто обеспечивает дополнительные преимущества в производительности!)
Это связано с тем, что NumPy выполняет множество операций, включая циклирование, на уровне C. Кроме того, NumPy оптимизирован для работы с векторами и позволяет избежать некоторых накладных расходов, связанных с Python.
Циклы Python for
Если вам нужны значения для итерации в цикле Python for
, то range
обычно является лучшим решением. Согласно официальной документации по Python:
Преимущество типа
range
перед обычнымиlist
илиtuple
заключается в том, что объектrange
всегда будет занимать один и тот же (небольшой) объем памяти, независимо от размера диапазона, который он представляет (поскольку в нем хранятся только значенияstart
,stop
иstep
, вычисляющие отдельные элементы и поддиапазоны по мере необходимости). (Источник)
range
часто это быстрее, чем arange()
при использовании в циклах Python for
, особенно когда есть возможность скоро выйти из цикла. Это происходит потому, что range
генерирует числа в ленивом режиме, по мере необходимости, по одному за раз.
В отличие от этого, arange()
генерирует все числа в начале.
Для получения дополнительной информации о range
вы можете ознакомиться с Функцией Python range() (руководство) и официальной документацией.
Другие процедуры, основанные на числовых диапазонах
В дополнение к arange()
, вы можете применить другие процедуры создания массива NumPy, основанные на числовых диапазонах:
linspace()
похож наarange()
в том, что возвращает числа с равномерным интервалом. Но вы можете указать количество генерируемых значений, а также указать, включать ли конечную точку и создавать ли несколько массивов одновременно.logspace()
иgeomspace()
аналогичныlinspace()
, за исключением того, что возвращаемые числа расположены равномерно по логарифмической шкале.meshgrid()
,ogrid()
, иmgrid()
возвращают сетки точек, представленные в виде массивов.
Все эти функции имеют свои особенности и варианты использования. Вы можете выбрать подходящую в соответствии с вашими потребностями.
Как вы уже видели, NumPy содержит дополнительные процедуры для создания экземпляров ndarray
.
Краткое описание
Чтобы использовать NumPy arange()
, вам необходимо сначала импортировать numpy
:
>>> import numpy as np
Вот таблица с несколькими примерами, в которых кратко описано, как использовать NumPy arange()
. Возможно, будет полезно запомнить различные варианты использования:
Example | Result |
---|---|
np.arange(start=1, stop=10, step=3) |
array([1, 4, 7]) |
np.arange(1, 10, 3) |
array([1, 4, 7]) |
np.arange(1, 10, 3, dtype=float) |
array([1., 4., 7.]) |
np.arange(1.0, 10, 3) |
array([1., 4., 7.]) |
np.arange(0, 1.1, 0.5) |
array([0. , 0.5, 1. ]) |
np.arange(2, 6) |
array([2, 3, 4, 5]) |
np.arange(5) |
array([0, 1, 2, 3, 4]) |
np.arange(-8, -2, 2) |
array([-8, -6, -4]) |
np.arange(7, 0, -3) |
array([7, 4, 1]) |
np.arange(8, 2) |
array([]) |
Не забывайте, что вы также можете повлиять на объем памяти, используемой для ваших массивов, указав NumPy dtypes с параметром dtype
.
Заключение
Теперь вы знаете, как использовать NumPy arange()
. Функция np.arange()
является одной из основных подпрограмм NumPy, часто используемых для создания экземпляров NumPy ndarray
. У него есть четыре аргумента:
start
: первое значение массиваstop
: где заканчивается массивstep
: увеличение или уменьшениеdtype
: тип элементов массива
Вы также узнали, как NumPy arange()
сравнивается со встроенным классом Python range
при создании последовательностей и генерации значений для повторения.
Вы видели, что существуют другие процедуры создания массивов NumPy на основе числовых диапазонов, такие как linspace()
, logspace()
, meshgrid()
, и так далее.