1. 程式人生 > 實用技巧 >Numpy索引與切片操作

Numpy索引與切片操作

Numpy索引與切片操作



單元素索引

一維資料的單元素索引是最簡單的一種索引方式,與Python列表的操作完全一致。

>>> x = np.arange(10)
>>> x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

>>> x[2]
2



二維以及多維資料的單元素索引與Python的列表操作並不完全一致。

在Numpy中提供了兩種對多維資料進行單元素索引的方法,這裡以二維資料為例。

>>> y = np.arange(12).reshape(3, 4)
>>> y
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

### 第一種索引方式
>>> y[1][2]
6

### 第二種索引方式
>>> y[1,2]
6

y[1] [2]和y[1, 2]都能對特定位置中的元素進行訪問,前者是Python列表和Numpy都支援的索引方式,後者只適用於Numpy。

第二種索引方式的效率高於第一種索引方式,原因在於第一種方法會在第一個方括號時建立一個臨時陣列來對第二個方括號進行索引。



按行列索引

如果一個多維陣列在索引時,索引數量少於其維度,那麼會得到一個子維的陣列。

>>> y
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

>>> y[0]
array([0, 1, 2, 3])



冒號和省略號語法用於完整的選擇出剩餘未指定維度的資料。

array([0, 1, 2, 3])
### 獲取第二行
>>> y[1, :]
array([4, 5, 6, 7])

>>> y[1, ...]
array([4, 5, 6, 7])

### 獲取第三列
>>> y[:, 2]
array([ 2,  6, 10])

>>> y[..., 2]
array([ 2,  6, 10])

在這裡冒號和省略號的功能是一致的。



切片操作

Numpy的切片操作與Python列表完全一致。[start_index : stop_index : step],預設第三個引數為1。具體可參考

徹底搞懂Python切片操作



拷貝整個陣列

在Numpy中提供了x[:]和x.copy()兩種方式對陣列進行拷貝。

>>> x = y[:]
>>> x
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

>>> z = y.copy()
>>> z
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])



但兩種方式有本質的區別。

x = y[:]只是將x指向了y的記憶體地址,並沒有重新分配記憶體空間,修改x的元素值會改變y相應位置的元素值。

z = y.copy()重新分配了記憶體空間,修改z的元素值不會改變y相應位置的元素值。

### 修改x,改變了y 
>>> y[1, 1]
5
>>> x[1, 1] = 0
>>> y[1, 1]
0

### 修改z, y不變
>>> y[2, 2]
10
>>> z[2, 2] = 0
>>> y[2, 2]
10



增加/降低陣列維度

有時候,資料處理的過程中,常常會遇到兩個資料的shape不匹配的情況。例如一張256 * 256的灰度圖,尺寸可能是(256, 256)或者(256, 256, 1),將(256, 256)轉換成(256, 256, 1)稱為增維,有以下幾種方法可以完成。

>>> x = np.arange(256 * 256).reshape(256, 256)
>>> x.shape
(256, 256)

### 第一種方法,直接使用reshape
>>> y = x.reshape(256, 256, 1)
>>> y.shape
(256, 256, 1)

### 第二種方法,這裡np.newaxis = None
>>> z = x[:, :, np.newaxis]
>>> z.shape
(256, 256, 1)

### 同時可以將np.newaxis放在其他位置,這樣相應的位置就會增加一個維度,長度為1
>>> a = x[:, np.newaxis, :]
>>> a.shape
(256, 1, 256)



降維的話,也可以直接使用reshape完成。

>>> y.shape
(256, 256, 1)
>>> y.reshape(256, 256).shape
(256, 256)



本文只列出了一些常用的方法,完整的操作請點選