如何创建具有规则间隔值的数组#

有一些 NumPy 函数在应用中类似,但提供略有不同的结果,如果不确定何时以及如何使用它们,可能会导致混淆.以下指南旨在列出这些函数并描述其建议用法.

这里提到的函数是

1D 域(间隔)#

linspace vs. arange#

numpy.linspacenumpy.arange 都提供了将间隔(1D 域)划分为等长子间隔的方法.这些分区将根据选择的起始点和结束点以及步长(子间隔的长度)而有所不同.

  • 如果需要整数步长,请使用 numpy.arange .

    numpy.arange 依赖于步长来确定返回数组中的元素数量,这不包括端点.这通过 arangestep 参数确定.

    示例:

    >>> np.arange(0, 10, 2)  # np.arange(start, stop, step)
    array([0, 2, 4, 6, 8])
    

    参数 startstop 应该是整数或实数,但不能是复数. numpy.arange 类似于 Python 内置的 range .

    浮点不准确性可能使具有浮点数的 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)
    

其他例子#

  1. 如果在 numpy.arange 中使用浮点数值作为 step ,可能会产生意想不到的结果.为了避免这种情况,请确保所有的浮点数转换都在结果计算之后进行.例如,将

    >>> 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
    
  2. 请注意

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

geomspacelogspace#

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 ( basestart 次方) 开始,到 base  stop 结束:

>>> np.logspace(2, 3, num=5, base=2)
array([4.        , 4.75682846, 5.65685425, 6.72717132, 8.        ])

N-D 域#

N-D 域可以被划分为网格.这可以通过以下函数之一来完成.

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')
../_images/meshgrid_plot.png

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. 这样可以避免重复数据,从而节省内存,这通常是可取的.

这些稀疏坐标网格旨在与 Broadcasting 一起使用. 当所有坐标都在表达式中使用时,广播仍然会导致一个完全维度的结果数组.

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