B09_NumPy迭代數組(控制遍歷順序,修改數組中元素的值,使用外部循環,廣播迭代)

NumPy迭代數組

NumPy 迭代器對象 numpy.nditer 提供了一種靈活訪問一個或者多個數組元素的方式。

迭代器最基本的任務的可以完成對數組元素的訪問。

接下來我們使用arange()函數創建一個 2 * 3 數組,並使用nditer對它進行迭代。
實例:

# -*- coding: UTF-8 -*-

import numpy as np

a = np.arange(6).reshape(2,3)
print('原始數組是:')
print(a)
print('\n')
print('迭代輸出元素:')
for x in np.nditer(a):
    print(x,end=",")
print('\n')

輸出結果爲:

原始數組是:
[[0 1 2]
 [3 4 5]]
迭代輸出元素:
0,1,2,3,4,5,

以上實例不是使用標準 C 或者 Fortran 順序,選擇的順序是和數組內存佈局一致的,這樣做是爲了提升訪問的效率,默認是行序優先(row-major order,或者說是 C-order)。

這反映了默認情況下只需訪問每個元素,而無需考慮其特定順序。我們可以通過迭代上述數組的轉置來看到這一點,並與以 C 順序訪問數組轉置的 copy 方式做對比,如下實例:

import numpy as np

a = np.arange(6).reshape(2,3)
print(a)
for x in np.nditer(a.T):
    print(x,end=",")
print('\n')

for x in np.nditer(a.T.copy(order='C')):
    print(x,end=",")
print('\n')

輸出結果爲:

[[0 1 2]
 [3 4 5]]
0,1,2,3,4,5,
0,3,1,4,2,5,

從上述例子可以看出,a 和 a.T 的遍歷順序是一樣的,也就是他們在內存中的存儲順序也是一樣的,但是 a.T.copy(order = ‘C’) 的遍歷結果是不同的,那是因爲它和前兩種的存儲方式是不一樣的,默認是按行訪問。

控制遍歷順序:

  • for x in np.nditer(a, order=‘F’):Fortran order,即是列序優先;
  • for x in np.nditer(a.T, order=‘C’):C order,即是行序優先;

實例:

import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始數組是:')
print(a)
print('\n')
print('原始數組的轉置是:')
b = a.T
print(b)
print('\n')
print('以 C 風格順序排序:')
c = b.copy(order='C')
print(c)
for x in np.nditer(c):
    print(x, end=", ")
print('\n')
print('以 F 風格順序排序:')
c = b.copy(order='F')
print(c)
for x in np.nditer(c):
    print(x, end=", ")

運行結果是:

原始數組是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
原始數組的轉置是:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
以 C 風格順序排序:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55, 
以 F 風格順序排序:
[[ 0 20 40]
 [ 5 25 45]
 [10 30 50]
 [15 35 55]]
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)
print('原始數組是:')
print(a)
print('\n')
print('以 C 風格順序排序:')
for x in np.nditer(a, order='C'):
    print(x, end=", ")
print('\n')
print('以 F 風格順序排序:')
for x in np.nditer(a, order='F'):
    print(x, end=", ")

輸出結果爲:

原始數組是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
以 C 風格順序排序:
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 
以 F 風格順序排序:
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55,

修改數組中元素的值:

nditer 對象有另一個可選參數 op_flags。 默認情況下,nditer 將視待迭代遍歷的數組爲只讀對象(read-only),爲了在遍歷數組的同時,實現對數組元素值得修改,必須指定 read-write 或者 write-only 的模式。
實例:

import numpy as np

a = np.arange(0, 60, 5)
a = a.reshape(3, 4)
print('原始數組是:')
print(a)
print('\n')
for x in np.nditer(a, op_flags=['readwrite']):
    x[...] = 2 * x
print('修改後的數組是:')
print(a)

實例:

原始數組是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
修改後的數組是:
[[  0  10  20  30]
 [ 40  50  60  70]
 [ 80  90 100 110]]

使用外部循環

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

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

在下面的實例中,迭代器遍歷對應於每列,並組合爲一維數組。
實例:

原始數組是:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
修改後的數組是:
[ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55],

廣播迭代

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

第一個數組爲:
[[ 0  5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
第二個數組爲:
[1 2 3 4]
修改後的數組爲:
0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章