如何建立具有規則間隔值的陣列#

NumPy 中有一些功能在應用上相似,但會產生略有不同的結果,如果不確定何時以及如何使用它們,可能會造成混淆。以下指南旨在列出這些功能並描述其建議用法。

這裡提到的函數有

1D 域(區間)#

linspace vs. arange#

numpy.linspacenumpy.arange 都提供了將區間(一維域)劃分為等長子區間的方法。這些劃分會根據選擇的起點和終點以及**步長**(子區間的長度)而有所不同。

  • 如果您想要整數步長,請使用 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 ** startbasestart 次方)開始,到 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')
../_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.mgridnumpy.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