Numpy基礎入門(5)廣播和迭代

學習彙總:點這裏

廣播

術語廣播是指 NumPy 在算術運算期間處理不同形狀的數組的能力。 對數組的算術運算通常在相應的元素上進行。 如果兩個陣列具有完全相同的形狀,則這些操作被無縫執行。

>>>import numpy as np 
>>>a = np.array([1,2,3,4]) 
>>>b = np.array([10,20,30,40]) 
>>>c = a * b 
>>>c
array([ 10,  40,  90, 160])

如果兩個數組的維數不相同,則元素到元素的操作是不可能的。 然而,在 NumPy 中仍然可以對形狀不相似的數組進行操作,因爲它擁有廣播功能。 較小的數組會廣播到較大數組的大小,以便使它們的形狀可兼容。
如果滿足以下規則,可以進行廣播:

  1. ndim較小的數組會在前面追加一個長度爲 1 的維度。
  2. 輸出數組的每個維度的大小是輸入數組該維度大小的最大值。
  3. 如果輸入在每個維度中的大小與輸出大小匹配,或其值正好爲 1,則在計算中可它。
  4. 如果輸入的某個維度大小爲 1,則該維度中的第一個數據元素將用於該維度的所有計算。

如果上述規則產生有效結果,並且滿足以下條件之一,那麼數組被稱爲可廣播的。

  1. 數組擁有相同形狀。
  2. 數組擁有相同的維數,每個維度擁有相同長度,或者長度爲 1。
  3. 數組擁有極少的維度,可以在其前面追加長度爲 1 的維度,使上述條件成立。
>>>import numpy as np 
>>>a = np.array([[0.0,0.0,0.0],[10.0,10.0,10.0],[20.0,20.0,20.0],[30.0,30.0,30.0]]) 
>>>b = np.array([1.0,2.0,3.0])  
>>>a
array([[  0.,   0.,   0.],
       [ 10.,  10.,  10.],
       [ 20.,  20.,  20.],
       [ 30.,  30.,  30.]])

>>>b
array([ 1.,  2.,  3.])

>>>a + b
array([[  1.,   2.,   3.],
       [ 11.,  12.,  13.],
       [ 21.,  22.,  23.],
       [ 31.,  32.,  33.]])

展示了數組b如何通過廣播來與數組a兼容。

迭代

NumPy 包包含一個迭代器對象numpy.nditer。 它是一個有效的多維迭代器對象,可以用於在數組上進行迭代。 數組的每個元素可使用 Python 的標準Iterator接口來訪問。

1.使用arange()函數創建一個 3X4 數組,並使用nditer對它進行迭代。

>>>import numpy as np
>>>a = np.arange(0,60,5) 
>>>a = a.reshape(3,4)  
>>>a
 array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])
 
>>>for x in np.nditer(a):  
    	print (x),
0 5 10 15 20 25 30 35 40 45 50 55

2.迭代的順序匹配數組的內容佈局,而不考慮特定的排序。 這可以通過迭代上述數組的轉置來看到。

>>>import numpy as np 
>>>a = np.arange(0,60,5) 
>>>a = a.reshape(3,4)  
>>>a
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])
       
>>>b = a.T 
>>>b
 array([[ 0, 20, 40],
       [ 5, 25, 45],
       [10, 30, 50],
       [15, 35, 55]])

>>>for x in np.nditer(b):  
    	print (x),
0 5 10 15 20 25 30 35 40 45 50 55

迭代順序

如果相同元素使用 F 風格順序存儲,則迭代器選擇以更有效的方式對數組進行迭代。

>>>import numpy as np 
>>>a = np.arange(0,60,5) 
>>>a = a.reshape(3,4)  
>>>a
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])
       
>>>b = a.T 
>>>b
 array([[ 0, 20, 40],
       [ 5, 25, 45],
       [10, 30, 50],
       [15, 35, 55]])

>>>c = b.copy(order='C')  
>>>print c 
array([[ 0, 20, 40],
       [ 5, 25, 45],
       [10, 30, 50],
       [15, 35, 55]])

>>>for x in np.nditer(c):  
    	print (x),  
0 20 40 5 25 45 10 30 50 15 35 55

>>>c = b.copy(order='F')  
>>>c
array([[ 0, 20, 40],
       [ 5, 25, 45],
       [10, 30, 50],
       [15, 35, 55]])

>>>for x in np.nditer(c):  
   		print (x),
0 5 10 15 20 25 30 35 40 45 50 55

可以通過顯式提醒,來強制nditer對象使用某種順序:

>>>import numpy as np 
>>>a = np.arange(0,60,5) 
>>>a = a.reshape(3,4)  
>>>a
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])

>>>for x in np.nditer(a, order =  'C'):  
   		print (x),  
0 5 10 15 20 25 30 35 40 45 50 55

>>>for x in np.nditer(a, order =  'F'):  
    	print (x),
0 20 40 5 25 45 10 30 50 15 35 55

修改數組的值

nditer對象有另一個可選參數op_flags。 其默認值爲只讀,但可以設置爲讀寫或只寫模式。 這將允許使用此迭代器修改數組元素。

>>>import numpy as np
>>>a = np.arange(0,60,5) 
>>>a = a.reshape(3,4)  
>>>a
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])

>>>for x in np.nditer(a, op_flags=['readwrite']): 
   			x[...]=2*x 
>>>a
array([[  0,  10,  20,  30],
       [ 40,  50,  60,  70],
       [ 80,  90, 100, 110]])

外部循環

nditer類的構造器擁有flags參數,它可以接受下列值:

序號 參數及描述
1 c_index 可以跟蹤 C 順序的索引
2 f_index 可以跟蹤 Fortran 順序的索引
3 multi-index 每次迭代可以跟蹤一種索引類型
4 external_loop 給出的值是具有多個值的一維數組,而不是零維數組

迭代器遍歷對應於每列的一維數組。

>>>import numpy as np 
>>>a = np.arange(0,60,5) 
>>>a = a.reshape(3,4)  
>>>a
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])

>>>for x in np.nditer(a, flags =  ['external_loop'], order =  'F'):  
    		print (x),
array([ 0, 20, 40]),
array([ 5, 25, 45]),
array([10, 30, 50]),
array([15, 35, 55]),

廣播迭代

如果兩個數組是可廣播的,nditer組合對象能夠同時迭代它們。 假設數組a具有維度 3X4,並且存在維度爲 1X4 的另一個數組b,則使用以下類型的迭代器(數組b被廣播到a的大小)。

>>>import numpy as np 
>>>a = np.arange(0,60,5) 
>>>a = a.reshape(3,4)  
>>>a
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])

>>>b = np.array([1,  2,  3,  4], dtype =  int)  
>>>b 
array([1, 2, 3, 4])

>>>for x,y in np.nditer([a,b]):  
    	print ( "%d:%d"  %  (x,y)),
0:1 5:2 10:3 15:4 20:1 25:2 30:3 35:4 40:1 45:2 50:3 55:4

字節交換

我們已經知道,存儲在計算機內存中的數據取決於 CPU 使用的架構。 它可以是小端(最小有效位存儲在最小地址中)或大端(最小有效字節存儲在最大地址中)。

numpy.ndarray.byteswap()函數在兩個表示:大端和小端之間切換。

>>>import numpy as np 
>>>a = np.array([1,  256,  8755], dtype = np.int16)  
>>>a
array([   1,  256, 8755], dtype=int16)
 
>>>map(hex,a)  
['0x1', '0x100', '0x2233']

# byteswap() 函數通過傳入 true 來原地交換 
>>>a.byteswap(True)  
array([  256,     1, 13090], dtype=int16)

# 我們可以看到字節已經交換了
>>>map(hex,a)  
['0x100', '0x1', '0x3322']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章