23 KiB
NumPy arange():如何使用 np.arange()
*立即观看**本教程有真实 Python 团队创建的相关视频课程。配合文字教程一起看,加深理解: 有效使用 NumPy 的 NP . arange()
NumPy 是数值计算的基本 Python 库。它最重要的类型是一个叫做ndarray的数组类型。NumPy 为不同的环境提供了许多数组创建例程。arange()是一个基于数值范围的函数。它通常被称为np.arange(),因为np是 NumPy 的一个广泛使用的缩写。
当您使用依赖 NumPy 数组的其他 Python 库时,创建 NumPy 数组是很重要的,比如 SciPy 、 Pandas 、 Matplotlib 、scikit-learn 等等。NumPy 适合创建和使用数组,因为它提供了有用的例程,使的性能提升,并允许您编写简洁的代码。
到本文结束时,你会知道:
- 什么是
np.arange() - 如何使用
np.arange() np.arange()与 Python 内置类range相比如何- 哪些套路和
np.arange()类似
让我们看看np.arange()的行动吧!
免费奖励: 点击此处获取免费的 NumPy 资源指南,它会为您指出提高 NumPy 技能的最佳教程、视频和书籍。
np.arange()的返回值和参数
NumPy arange()是一个基于数值范围的数组创建例程。它创建一个具有等间距值的ndarray实例,并返回对它的引用。
您可以使用四个参数arange()定义数组中包含的值的间隔、它们之间的空间以及它们的类型:
numpy.arange([start, ]stop, [step, ], dtype=None) -> numpy.ndarray
前三个参数确定值的范围,而第四个参数指定元素的类型:
start是定义数组中第一个值的数字(整数或小数)。stop是定义数组结尾的数字,不包含在数组中。step是定义数组中每两个连续值之间的间距(差)的数字,默认为1。dtype是输出数组的元素类型,默认为None。
step不能为零。否则你会得到一个ZeroDivisionError。如果增量或减量是0,你就不能离开start的任何地方。
如果省略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()的一种直观而简洁的方式。在这个例子中使用关键字参数并没有真正提高可读性。
**注意:**如果你提供两个位置参数,那么第一个是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 数组的最常用方法,该数组从零开始,增量为 1。
**注意:**单个参数定义了计数停止的位置。输出数组从0开始,增量为1。
如果你试图显式地提供没有start的stop,那么你将得到一个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之前结束。
倒数计时
有时你会希望数组的值从左到右递减。在这种情况下,您可以使用负值的step和大于stop的start:
>>> 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。计数在此停止,因为在下一个值(-2)之前到达了stop ( 0)。
您可以在下图中看到此示例的图形表示:
同样,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为负值的变体更优雅简洁。
获取空数组
在一些极端情况下,您可以使用arange()获得空的 NumPy 数组。这些是没有任何元素的常规实例。
如果您为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 dtypes 比 Python 的内置数字类型允许更细的粒度。
- 在某些情况下,NumPy dtypes 的别名对应于 Python 内置类型的名称。
- 通常,NumPy 例程可以接受 Python 数字类型,反之亦然。
- 一些 NumPy 数据类型具有依赖于平台的定义。
如果你想了解更多关于 NumPy 数组的 dtypes,那么请阅读官方文档。
你可以随意省略dtype。在这种情况下,arange()将尝试推导出结果数组的 dtype。这取决于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。这就是为什么数组x的 dtype 会是 NumPy 提供的整数类型之一。在这种情况下,NumPy 默认选择int64 dtype。这是一个 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到127np.uint8: 8 位无符号整数(从0到255np.int16: 16 位有符号整数(从-32768到32767np.uint16: 16 位无符号整数(从0到65535np.int32: 32 位有符号整数(从-2**31到2**31-1np.uint32: 32 位无符号整数(从0到2**32-1np.int64: 64 位有符号整数(从-2**63到2**63-1np.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 字节)。
当您的参数是十进制数而不是整数时,dtype 将是某种 NumPy 浮点类型,在本例中为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是一个整数,但是 dtype 是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
这就是如何获得包含元素[0, 1, 2, 3, 4, 5]的ndarray实例,并将其整形为二维数组。
range和np.arange()的比较
Python 有一个内置的类range,某种程度上类似于 NumPy arange()。range和np.arange()在应用和性能方面有重要区别。你会看到他们的不同和相似之处。
两者的主要区别在于range是内置的 Python 类,而arange()是属于第三方库(NumPy)的函数。
另外,他们的目的不一样!一般来说,当你需要使用 Python for循环来迭代时,range更合适。如果你想创建一个 NumPy 数组,并在幕后应用快速循环,那么arange()是一个更好的解决方案。
参数和输出
range和arange()具有相同的参数,这些参数定义了所获得数字的范围:
startstopstep
即使在start和stop相等的情况下,您也可以类似地应用这些参数。
然而,在使用range时:
- 您必须提供整数参数。否则,你会得到一个
TypeError。 - 您不能指定生成的数字的类型。总是
int。
range和arange()的返回类型也不同:
range创建该类的一个实例,该实例具有与其他序列(如list和tuple)相同的特性,如成员、连接、重复、切片、比较、长度检查等等。arange()返回 NumPyndarray的一个实例。
创建序列
您可以应用range来创建一个list或tuple的实例,在预定义的范围内均匀分布数字。你可能会发现理解特别适合这个目的。
然而,创建和操作 NumPy 数组通常比处理列表或元组更快,更 T2,更优雅。
让我们比较一下使用理解力创建一个list和使用arange()创建一个等价的 NumPy ndarray的性能:
>>> 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值重复这段代码,在我的机器上产生了以下结果:
尺寸:n |
每循环时间:range |
每循环时间:arange() |
比例 |
|---|---|---|---|
| one | 497 纳秒 | 1.14 秒 | Zero point four one |
| Ten | 2.24 秒 | 1.28 秒 | One point seven four |
| One hundred | 20.0 秒 | 1.37 秒 | Fourteen point six |
| One thousand | 211 s | 2.92 秒 | Seventy-two point three |
这些结果可能会有所不同,但是很明显,创建 NumPy 数组比创建 list 要快得多,除了长度非常短的序列。(应用程序通常会带来额外的性能优势!)
这是因为 NumPy 在 C 层执行许多操作,包括循环。此外,NumPy 为处理向量进行了优化,避免了一些与 Python 相关的开销。
Python for循环
如果您需要在 Python for循环中迭代值,那么range通常是更好的解决方案。根据官方 Python 文档:
与常规的
list或tuple相比,range类型的优势在于,range对象将总是占用相同(少量)的内存,无论它所代表的范围大小如何(因为它只存储根据需要计算单个项目和子范围的start、stop和step值)。(来源)
在 Python 的for循环中使用时,range通常比arange()快,尤其是当循环有可能很快中断的时候。这是因为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()。记住各种用法可能会有帮助:
| 例子 | 结果 |
|---|---|
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([]) |
不要忘记,您还可以通过用参数dtype指定 NumPy dtypes 来影响用于数组的内存。
结论
你现在知道如何使用 NumPy arange()。函数np.arange()是基本的 NumPy 例程之一,通常用于创建 NumPy ndarray的实例。它有四个论点:
start: 数组的第一个值stop: 数组结束的地方step: 增量或减量dtype: 数组的元素的类型
您还了解了在创建序列和生成要迭代的值时,NumPy arange()与 Python 内置类range的比较。
您看到了还有其他基于数值范围的 NumPy 数组创建例程,比如linspace()、logspace()、meshgrid()等等。
如果你有任何问题或意见,请写在下面的评论区。
立即观看本教程有真实 Python 团队创建的相关视频课程。配合文字教程一起看,加深理解: 有效使用 NumPy 的 NP . arange()*****

