NumPy 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() сравнивается со встроенным классом Python range
  • Какие процедуры похожи на np.arange()

Давайте посмотрим на np.arange() в действии!

Возвращаемое значение и параметры np.arange()

NumPy arange() - это одна из процедур создания массивов, основанная на числовых диапазонах. Он создает экземпляр ndarray с равномерно распределенными значениями и возвращает ссылку на него.

Вы можете определить интервал значений, содержащихся в массиве, расстояние между ними и их тип с помощью четырех параметров arange():

numpy.arange([start, ]stop, [step, ], dtype=None) -> numpy.ndarray

Первые три параметра определяют диапазон значений, в то время как четвертый определяет тип элементов:

  1. start это число (целое или десятичное), которое определяет первое значение в массиве.
  2. stop это число, которое определяет конец массива и не входит в него.
  3. step это число, которое определяет интервал (разницу) между каждыми двумя последовательными значениями в массиве и по умолчанию равно 1.
  4. 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() вывел это за вас. Вы узнаете больше об этом позже в статье.

Вы можете увидеть графическое представление этих трех примеров на рисунке ниже:

NumPy arange() in action

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).

Вы можете увидеть графическое представление этого примера на рисунке ниже:

NumPy arange() in action

Опять же, 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() возвращает экземпляр NumPy ndarray.

Создание последовательностей

Вы можете применить 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. У него есть четыре аргумента:

  1. start: первое значение массива
  2. stop: где заканчивается массив
  3. step: увеличение или уменьшение
  4. dtype: тип элементов массива

Вы также узнали, как NumPy arange() сравнивается со встроенным классом Python range при создании последовательностей и генерации значений для повторения.

Вы видели, что существуют другие процедуры создания массивов NumPy на основе числовых диапазонов, такие как linspace(), logspace(), meshgrid(), и так далее.

Back to Top