NumPy 學習筆記(二)
數組索引:
1、ndarray對象的內容可以通過索引或切片來訪問和修改,與 Python 中 list 的切片操作一樣;
由於數組可能是多維的,所以必須為數組的每個維度指定一個切片,使用切片時返回的是一個子數組
2、整數索引:獲取相應下標的元素的值
3、布爾數組索引:布爾索引通過布爾運算來獲取符合指定條件的元素的數組
4、花式索引:不同的索引之間可以相互搭配,同時也可以和切片一起使用
import numpy as np arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 切片,返回 arr[:2][1:] 的相應元素arr_t = arr[:2, 1:] # 輸出 arr_t: [[2 3] [5, 6]] print("arr[:2, 1:]: ", arr_t) # 整數索引允許使用相應下標組成的多維數組 # 這裏輸出 arr[0][1], arr[1][-1], arr[-1][0] arr_t = arr[[0, 1, -1], [1, -1, 0]] print("arr_t: ", arr_t) # 輸出 arr_t: [2 6 7] # 布爾索引使用布爾運算選出符合條件的元素 arr_t = arr[arr > 5] print("arr > 5:", arr_t) arr_t = arr[arr % 2 == 1] # [6 7 8 9] print("arr % 2 == 1: ", arr_t) # [1 3 5 7 9] # 組合索引 # arr[row, col] row指定行,col 指定列,其切片方法與 python 操作一樣 arr_t = arr[::2, ::2] print("arr[::2, ::2]: ", arr_t) # 輸出 [[1 3] [7 9]] # 對元素值大於 5 的元素組成的子數組進行切片 arr_t = arr[arr > 5][::2]print("arr[arr > 5][::2]: ", arr_t) # 輸出 [6 8] # 對行進行切片,同時獲取列為 0 的元素,這裏為 arr[1][0], arr[2][0] arr_t = arr[1:, 0] print("arr[1:, 0]: ", arr_t) # 輸出 [4 7] arr_t = arr[-1, :] print("arr[-1, :]: ", arr_t) # 同理,輸出 [7 8 9]
NumPy 廣播:
1、廣播是 numpy 對不同形狀(shape)的數組進行數值計算的方式
2、如果兩個數組 a 和 b 形狀相同,即滿足 a.shape == b.shape,那麽 a 與 b 的算術運算在對應位進行
3、廣播規則:
①讓所有輸入數組都向其中形狀最長的數組看齊,形狀中不足的部分都通過在前面加 1 補齊
②輸出數組的形狀是輸入數組形狀的各個維度上的最大值
③如果輸入數組的某個維度和輸出數組的對應維度的長度相同或者其長度為 1 時,這個數組能夠用來計算,否則出錯
④當輸入數組的某個維度的長度為 1 時,沿著此維度運算時都用此維度上的第一組值
import numpy as np one = np.arange(1, 26) # 修改數組形狀為 5*5 one.shape = (5, 5) print("one: ", one) # 生成 [50...25) 的數組 two = np.arange(50, 25, -1) two.shape = (5, 5) print("two: ", two) print("one + two: ", one + two) arr_one = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) arr_two = np.array([1, 2, 3, 4]) # 輸出 [[2 3 6 8] [6 8 10 12]] print("arr_one + arr_two: ", arr_one + arr_two) arr_two = np.array([[1], [2]]) # 輸出 [[2 3 4 5] [7 8 9 10]] print("arr_one + arr_two: ", arr_one + arr_two) arr_two = np.array([2]) # 輸出 [[2 4 6 8] [10 12 14 16]] print("arr_one * arr_two: ", arr_one * arr_two)
叠代數組:
1、NumPy 1.6 中引入的叠代器對象 nditer
提供了許多靈活的方式來以系統的方式訪問一個或多個數組的所有元素
2、nditer 使用標準 Python 叠代器接口逐個提供每個元素
3、nditer
對象提供了一個 order 參數來控制叠代的順序,默認 order="K",即保持原有順序
4、默認情況下,nditer 將輸入數組視為只讀對象。 要修改數組元素,必須指定讀寫或只寫模式
5、外部循環:若不使用外部循環,則數組的每個元素由叠代器一次提供一個;我們可以將一維最內層循環移動到叠代器外部的代碼中,
通過強制‘C‘和‘F‘順序,而得到不同的外部循環大小。 需要我們通過指定叠代器標誌來啟用此模式
import numpy as np # 產生 [0, 2pi] 的等差數組,其元素個數為 9 arr = np.linspace(0, 2 * np.pi, 9) arr.shape = (3, 3) print("Order is C") # 按行 for o in np.nditer(arr): print(o) print("Order is F") # 按列 for o in np.nditer(arr.copy(order="F")): print(o) # 默認情況下,nditer將輸入數組視為只讀對象。 要修改數組元素,必須指定讀寫或只寫模式 arr = np.arange(6).reshape(2, 3) for o in np.nditer(arr): o = o*2 print("arr: ", arr) # 沒有改變 for o in np.nditer(arr, op_flags=["readwrite"]): # 註意需要使用省略號索引 o[...] = o*2 print("arr: ", arr) # 外部循環 arr = np.linspace(1, 6, 6).reshape(2, 3) # 輸出 [1. 2. 3. 4. 5. 6.] 註意和之前的區別 for o in np.nditer(arr, flags=["external_loop"]): print("arr: ", o) time = 0 # 通過強制‘C‘和‘F‘順序,我們得到不同的外部循環大小 for o in np.nditer(arr, flags=["external_loop"], order="F"): print("arr", time, ": ", o) time += 1 # 跟蹤索引 # 跟蹤索引或多索引與使用外部循環不兼容,因為它需要每個元素具有不同的索引值 it = np.nditer(arr, flags=["multi_index"]) lst = [] while not it.finished: print("value: {}\nmulti_index: <{}>".format(it[0], it.multi_index)) lst.append(it.multi_index[1] - it.multi_index[0]) it.iternext() print("All it.multi_index[1] - it.multi_index[0]: ", lst)
註:Python中的常規賦值只是更改本地或全局變量字典中的引用,而不是修改現有變量。 這意味著簡單地分配給 x 不會將值放入數組的元素中,
而是將 x 作為數組元素引用切換為對指定值的引用。 要實際修改數組的元素,x應該用省略號索引
NumPy 學習筆記(二)