Numpy 筆記: 多維陣列的切片(slicing)和索引(indexing)【轉】
目錄
- 切片(slicing)操作
- 索引(indexing) 操作
- 最簡單的情況
- 獲取多個元素
- 切片和索引的同異
切片(slicing)操作
Numpy 中多維陣列的切片操作與 Python 中 list 的切片操作一樣,同樣由 start, stop, step 三個部分組成
import numpy as np arr = np.arange(12) print 'array is:', arr slice_one = arr[:4]print 'slice begins at 0 and ends at 4 is:', slice_one slice_two = arr[7:10] print 'slice begins at 7 and ends at 10 is:', slice_two slice_three = arr[0:12:4] print 'slice begins at 0 and ends at 12 with step 4 is:', slice_three array is: [ 0 1 2 3 4 5 6 7 8 9 10 11] slice begins at 0 and ends at 4 is: [0 1 2 3] slice begins at 7 and ends at 10 is: [7 8 9] slice begins at 0 and ends at 12 with step 4 is: [0 4 8]
上述例子是一維陣列的例子,如果是多維陣列,將不同維度上的切片操作用 逗號 分開就好了
# coding: utf-8 import numpy as np arr = np.arange(12).reshape((3, 4)) print 'array is:' print arr# 取第一維的索引 1 到索引 2 之間的元素,也就是第二行 # 取第二維的索引 1 到索引 3 之間的元素,也就是第二列和第三列 slice_one = arr[1:2, 1:3] print 'first slice is:' print slice_one # 取第一維的全部 # 按步長為 2 取第二維的索引 0 到末尾 之間的元素,也就是第一列和第三列 slice_two = arr[:, ::2] print 'second slice is:' print slice_two array is: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] first slice is: [[5 6]] second slice is: [[ 0 2] [ 4 6] [ 8 10]]
對於 slice_two,如果 arr 是用 Python 的 list 表示的,那麼要得到相同的結果得像下面這樣,相對來說就麻煩多了:
import numpy as np arr = np.arange(12).reshape((3, 4)).tolist() slice_two = [ row[::2] for row in arr ] print slice_two [[0, 2], [4, 6], [8, 10]]
對於維數超過 3 的多維陣列,還可以通過 '…' 來簡化操作
# coding: utf-8 import numpy as np arr = np.arange(24).reshape((2, 3, 4)) print arr[1, ...] # 等價於 arr[1, :, :] print arr[..., 1] # 等價於 arr[:, :, 1] [[12 13 14 15] [16 17 18 19] [20 21 22 23]] [[ 1 5 9] [13 17 21]]
索引(indexing) 操作
最簡單的情況
對於一個多維陣列來說,最簡單的情況就是訪問其中一個特定位置的元素了,如下所示:
# coding: utf-8 import numpy as np arr = np.array([ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16] ]) print '第二行第二列的值:', arr[1, 1] 第二行第二列的值: 4
相比之下,如果用 Python 的 list 來表示上述二維陣列,獲取同一個位置的元素的方法為:
# coding: utf-8 arr = [ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16] ] print '第二行第二列的值:', arr[1][1] try: print '第二行第二列的值(嘗試用 Numpy 的方式獲取):', arr[1, 1] except Exception as e: print str(e) 第二行第二列的值: 4 第二行第二列的值(嘗試用 Numpy 的方式獲取): list indices must be integers, not tuple
如果只是二維陣列,這種差別可能看起來並不大,但想象一下假如有一個 10 維的陣列,用 Python 的標準做法需要寫 10 對中括號,而用 Numpy 依然只需要一對。
獲取多個元素
事實上,在 Numpy 的索引操作方式 `x = arr[obj]` 中, obj 不僅僅可以是一個用逗號分隔開的數字序列,還可以是更復雜的內容。
-
用逗號分隔的陣列序列
- 序列的長度和多維陣列的維數要一致
- 序列中每個陣列的長度要一致
import numpy as np arr = np.array([ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16] ]) print arr[[0, 2], [3, 1]] [4 6]
以上面這個例子來說,其含義是: 選擇第一行和第三行,然後對第一行選擇第四列,對第三行選擇第二列。
-
boolean/mask index
這個不太好翻譯,所以就用原來的英語表達。
所謂 boolean index,就是用一個由 boolean 型別值組成的陣列來選擇元素的方法。比如說對下面這樣多維陣列
array([[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16]])
如果要取其中 值大於 5 的元素,就可以用上 boolean index 了,如下所示:
import numpy as np arr = np.array([[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16]]) mask = arr > 5 print 'boolean mask is:' print mask print arr[mask] boolean mask is: [[False False False False] [False False True True] [False True True True] [False True True True]] [ 6 8 6 9 12 8 12 16]
除了比較運算能產生 boolean mask 陣列以外, Numpy 本身也提供了一些工具方法:
- numpy.iscomplex
- numpy.isreal
- numpy.isfinite
- numpy.isinf
- numpy.isnan
切片和索引的同異
切片和索引都是訪問多維陣列中元素的方法,這是兩者的共同點,不同之處有:
- 切片得到的是原多維陣列的一個 檢視(view) ,修改切片中的內容會導致原多維陣列的內容也發生變化
- 切片得到在多維陣列中連續(或按特定步長連續)排列的值,而索引可以得到任意位置的值,自由度更大一些
不考慮第一點的話,切片的操作是可以用索引操作來實現的,不過這沒有必要就是了。
對於第一點,見下面的實驗:
import numpy as np arr = np.arange(12).reshape(2, 6) print 'array is:' print arr slc = arr[:, 2:5] print 'slice is:' print slc slc[1, 2] = 10000 print 'modified slice is:' print slc print 'array is now:' print arr
array is: [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11]] slice is: [[ 2 3 4] [ 8 9 10]] modified slice is: [[ 2 3 4] [ 8 9 10000]] array is now: [[ 0 1 2 3 4 5] [ 6 7 8 9 10000 11]]
轉自http://www.zmonster.me/2016/03/09/numpy-slicing-and-indexing.html