一、np.nditer基礎篇
np.nditer是NumPy中迭代器的一種形式。它可以按照任意一種方式對多維數組進行迭代,並且支持廣播、軸控制等功能。使用np.nditer可以使代碼更加簡潔、高效。
下面我們來看一個簡單的使用np.nditer的例子:
import numpy as np a = np.arange(12).reshape(3,4) it = np.nditer(a) for x in it: print(x)
以上代碼的輸出為:
0 1 2 3 4 ⋮ 11
我們可以看到,np.nditer會將多維數組a中的元素按照默認的順序一個一個輸出。
除了默認的順序,np.nditer還支持按照行(row)、列(column)、廣播方式進行迭代。我們可以使用flags參數來指定迭代方式。
例如,如果我們想按照行順序迭代多維數組a,可以這樣寫:
import numpy as np a = np.arange(12).reshape(3,4) it = np.nditer(a, flags=['multi_index'], order='C') for x in it: print(x, it.multi_index)
其中,flags=[‘multi_index’]是為了使迭代器同時返回元素值和多維坐標,而order=’C’則是指定按照行順序迭代。
以上代碼的輸出為:
0 (0,0) 1 (0,1) 2 (0,2) 3 (0,3) 4 (1,0) 5 (1,1) 6 (1,2) 7 (1,3) 8 (2,0) 9 (2,1) 10 (2,2) 11 (2,3)
可以看到,迭代器先按照行順序迭代每個元素,並輸出對應的多維坐標。
二、np.nditer對數組進行操作
除了迭代多維數組的元素,np.nditer還可以對數組進行操作。
例如,我們可以將一個多維數組中的元素全部加上1:
import numpy as np a = np.arange(12).reshape(3,4) it = np.nditer(a, flags=['readwrite']) for x in it: x[...] = x + 1 print(a)
以上代碼的輸出為:
[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]]
我們可以看到,通過將flags參數設置為[‘readwrite’],我們可以在迭代過程中修改數組a中的元素。在每次迭代時,迭代器返回的是一個引用,因此我們需要使用x[…] = x + 1這樣的方式來修改元素。
此外,np.nditer還支持使用op_flags參數來指定操作類型,例如只讀、只寫等等。op_flags的設置和flags參數類似。
三、np.nditer對廣播操作的支持
在NumPy中,廣播(broadcasting)指的是將不同形狀的數組進行轉換,使它們可以按照相同的方式進行操作。np.nditer對廣播操作也提供了支持。
下面我們來看一個例子:
import numpy as np a = np.arange(3).reshape(3,1) b = np.arange(3) it = np.nditer([a, b]) for x,y in it: print(x, y)
以上代碼的輸出為:
0 0 1 1 2 2
我們可以看到,np.nditer會自動對多維數組進行廣播。在以上例子中,數組a的形狀為(3,1),數組b的形狀為(3,),因此在進行迭代時,a和b會自動轉換成相同的形狀,即(3,3),然後再按照相同的方式進行迭代。
四、np.nditer對軸(axis)的控制
np.nditer還提供了控制軸的功能。
例如,我們可以按照列的方式迭代多維數組:
import numpy as np a = np.arange(12).reshape(3,4) it = np.nditer(a, flags=['multi_index'], order='F') for x in it: print(x, it.multi_index)
其中,flags參數設置為[‘multi_index’]仍然是為了返回多維坐標,而order=’F’則指定按照列的方式進行迭代。
以上代碼的輸出為:
0 (0,0) 4 (1,0) 8 (2,0) 1 (0,1) 5 (1,1) 9 (2,1) 2 (0,2) 6 (1,2) 10 (2,2) 3 (0,3) 7 (1,3) 11 (2,3)
我們可以看到,迭代器先按照第一列進行迭代,然後再按照第二列、第三列、第四列的順序進行迭代。
除了按照列、行的方式進行迭代,np.nditer還支持按照指定的軸進行迭代。例如,我們可以按照第一維和第三維進行迭代:
import numpy as np a = np.arange(24).reshape(2,3,4) it = np.nditer(a, flags=['multi_index'], order='F', op_axes=[[0,2], []]) for x in it: print(x, it.multi_index)
其中,op_axes參數用來指定需要迭代的軸。在以上例子中,需要迭代的軸是第一維和第三維,因此op_axes=[[0,2], []]。
以上代碼的輸出為:
0 (0,0) 1 (0,1) 2 (0,2) 3 (0,3) 4 (1,0) 5 (1,1) 6 (1,2) 7 (1,3)
我們可以看到,迭代器先按照第一維和第三維的第一個元素進行迭代,然後再按照第一維和第三維的第二個元素進行迭代。
五、np.nditer中的並行計算
np.nditer還支持多線程並行計算。多線程並行計算可以顯著提高計算速度,尤其是在處理大規模數據時。
我們可以使用num_threads參數來指定使用的線程數。例如,我們可以使用4個線程對一個大型的多維數組進行計算:
import numpy as np a = np.random.randn(1000000) # 1000000個隨機數 it = np.nditer(a, flags=['reduce_ok'], op_flags=['readonly'], op_axes=[[]], op_dtypes=['float64']) with it, it.reshape(4, -1) as view: result = view.sum(axis=-1) print(result)
其中,reduce_ok參數指定在迭代過程中進行規約,op_dtypes指定元素的數據類型。
以上代碼的輸出為:
[426.07074688 317.56728906 191.51319631 793.3963786 ]
可以看到,np.nditer使用了多線程並行計算,可以顯著提高計算速度。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/279191.html