1. 程式人生 > >ndarray陣列的索引和切片

ndarray陣列的索引和切片

索引:獲取陣列中特定位置元素的過程

切片:獲取陣列元素子集的過程

import numpy as np

一維陣列

一維陣列的索引和切片與python中的列表類似

索引:若元素個數為n,則索引下標可表示為[0,1,2,...,n-1]或[-n,-(n-1),-(n-2),...,-2,-1]

print('*'*8+'一維陣列的索引和切片'+'*'*8)
# 若元素個數為n,則索引下標可表示為[0,1,2,...,n-1]或[-n,-(n-1),-(n-2),...,-2,-1]
ar1 = np.array([5, 6, 7, 8, 9])
print(ar1[4])   # 索引自左向右從下標0開始
print(ar1[-2])  # 索引自右向左從下標-1遞減,最右邊為-1,相鄰的為-2

切片:切片可用三元素冒號分割

ar1[起始編號 : 終止編號(不含) : 步長],起始編號預設是0,終止編號預設是n,步長預設是1

仍然是ndarray陣列
b = ar1[1:4:2]
print(b)
print(type(b))

多維陣列

ar2 = np.arange(24).reshape((2, 3, 4))
print('*'*8+'多維陣列的索引和切片'+'*'*8)

多維陣列的索引,每個維度一個索引值,逗號分隔————r2[ax0上索引,ax1上索引,ax2上索引],各個維度索引和一維相同0~n-1-n~-1

print(ar2)
print(ar2[1, 1, 2])
print(ar2[-1, -2, -2])

多維陣列的切片,逗號分隔,每個維度同一維切片一樣,用三冒號分隔, 如果只有一個:表示選取整個維度

print(ar2[:, 1:3, :])
print(ar2[:, 1:3, ::2])
print(ar2[:, 1, -3])

索引陣列:將陣列作為索引,通常是一維陣列(每個元素代表對應維度索引)

1.布林索引

布林陣列:顧名思義,元素型別為布林值的陣列,同樣可以是一維或者多維陣列

例如:bool_arr1 = np.array([True, False, False, False, False, False,True])

如下的陣列定義也是布林陣列

names = np.array(['Liu', 'Zhang', 'Li', 'Wang', 'Sun', 'Zong', 'Kong'])
bool_arr2 = names == 'Zhang'

此時bool_arr2array[False True False False False False False]

若想得到bool_arr1,則:bool_arr1 = (names == 'Liu') | (names == 'Kong')

同樣的,與 &非 ~不等於 !=>=<=><等條件判斷同樣可以用於布林陣列賦值語句裡。

注意!Python中的關鍵字andor對布林值陣列並沒有用,is在特殊情況可能會有效,即判斷兩個布林陣列是否相等

如:bool_arr3 = ~(names == 'Zhang')等價於boo_arr3 = names != 'Zhang'

一維布林陣列 作為 布林索引陣列,例如:

names = np.array(['Liu', 'Zhang', 'Li', 'Wang', 'Sun', 'Zong', 'Kong'])
bool_arr2 = names == 'Zhang'
data = np.arange(21).reshape((7,3))
print(data)
print(data[bool_arr2])

輸出為:

[[ 0  1  2]
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]
 [12 13 14]
 [15 16 17]
 [18 19 20]] # data
 
[[3 4 5]]   # data[bool_arr2]

2.神奇索引

使用整數陣列作為資料索引陣列,整數陣列可以是一維或多維

2.1一維資料索引陣列

一維資料索引陣列傳遞包含指定順序的列表或陣列。即:

一維資料索引資料每個元素i代表陣列軸axis=0上,即取第1維的第i個數據。

例1:

data1 = np.arange(28).reshape((7, 4))
print(data1)
print('-'*20 + 'data1[[1, 5, 6, 2, 1]]' + '-'*20)
print(data1[[1, 5, 6, 2, 1]])
print('-'*20 + 'data1[[-1, 3, -2, -5, 1]]' + '-'*20)
print(data1[[-1, 3, -2, -5, 1]])

輸出為:

[[ 0  1  2  3]  # 0或-7
 [ 4  5  6  7]  # 1或-6
 [ 8  9 10 11]  # 2或-5
 [12 13 14 15]  # 3或-4
 [16 17 18 19]  # 4或-3
 [20 21 22 23]  # 5或-2
 [24 25 26 27]] # 6或-1
--------------------data1[[1, 5, 6, 2, 1]]--------------------
[[ 4  5  6  7]
 [20 21 22 23]
 [24 25 26 27]
 [ 8  9 10 11]
 [ 4  5  6  7]]
--------------------data1[[-1, 3, -2, -5, 1]]--------------------
[[24 25 26 27]
 [12 13 14 15]
 [20 21 22 23]
 [ 8  9 10 11]
 [ 4  5  6  7]]

例2:

data2 = np.arange(48).reshape((4, 4, 3))
print(data2)
print('-'*20 + 'data2[[3, 0, 2, 1, 0]]' + '-'*20)
print(data2[[3, 0, 2, 1, 0]])
print('-'*20 + 'data2[[-1, -2, 1, 2]]' + '-'*20)
print(data2[[-1, -2, 1, 2]])

輸出為:

[[[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]
  [ 9 10 11]]   # 0或-4

 [[12 13 14]
  [15 16 17]
  [18 19 20]
  [21 22 23]]   # 1或-3

 [[24 25 26]
  [27 28 29]
  [30 31 32]
  [33 34 35]]   # 2或-2

 [[36 37 38]
  [39 40 41]
  [42 43 44]
  [45 46 47]]]  # 3或-1
--------------------data2[[3, 0, 2, 1, 0]]--------------------
[[[36 37 38]
  [39 40 41]
  [42 43 44]
  [45 46 47]]

 [[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]
  [ 9 10 11]]

 [[24 25 26]
  [27 28 29]
  [30 31 32]
  [33 34 35]]

 [[12 13 14]
  [15 16 17]
  [18 19 20]
  [21 22 23]]

 [[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]
  [ 9 10 11]]]
--------------------data2[[-1, -2, 1, 2]]--------------------
[[[36 37 38]
  [39 40 41]
  [42 43 44]
  [45 46 47]]

 [[24 25 26]
  [27 28 29]
  [30 31 32]
  [33 34 35]]

 [[12 13 14]
  [15 16 17]
  [18 19 20]
  [21 22 23]]

 [[24 25 26]
  [27 28 29]
  [30 31 32]
  [33 34 35]]]

data2是多維陣列,其在軸axis=0共有4個數據,每個資料其實又是一個數組

2.2 多個索引陣列

傳遞多個索引陣列作為索引時,會根據每個索引陣列對應元素選出一個一維陣列

每個索引陣列大小應相同,設為n陣列個數應等於資料陣列的維數,相當於得到n個點的座標,座標分量即為資料陣列對應維度。

例:

data3 = np.arange(32).reshape((8, 4))
print(data3)
print('-'*20 + 'data3[[1, 5, 7, 2], [0, 3, 1, 2]]' + '-'*20)
print(data3[[1, 5, 7, 2], [0, 3, 1, 2]])
data4 = np.arange(48).reshape((4, 4, 3))
print('-'*20 + 'data4' + '-'*40)
print(data4)
print('-'*20 + 'ddata4[[3, 3, 1, 2, 0], [2, 1, 2, 0, 3], [2, 2, 0, 2, 1]' + '-'*20)
print(data4[[3, 3, 1, 2, 0], [2, 1, 2, 0, 3], [2, 2, 0, 2, 1]])

輸出為:

   0  1  2  3   #  “座標”
0[[ 0  1  2  3]
1 [ 4  5  6  7]
2 [ 8  9 10 11]
3 [12 13 14 15]
4 [16 17 18 19]
5 [20 21 22 23]
6 [24 25 26 27]
7 [28 29 30 31]]
--------------------data3[[1, 5, 7, 2], [0, 3, 1, 2]]--------------------
[ 4 23 29 10]
--------------------data4----------------------------------------
[[[ 0  1  2]
  [ 3  4  5]       # 0(axis=0)
  [ 6  7  8]
  [ 9 10 11]]

 [[12 13 14]
  [15 16 17]      # 1
  [18 19 20]
  [21 22 23]]

 [[24 25 26]
  [27 28 29]      # 2
  [30 31 32]
  [33 34 35]]

 [[36 37 38]
  [39 40 41]     # 3
  [42 43 44]
  [45 46 47]]]
--------------------ddata4[[3, 3, 1, 2, 0], [2, 1, 2, 0, 3], [2, 2, 0, 2, 1]--------------------
[44 41 18 26 10]

data3[[1, 5, 7, 2], [0, 3, 1, 2]] 即為“座標“(1,0)、(5,3)、(7,1)、(2,2)的元素被選中。

data4是一個三維陣列,在0軸上,又是一個二維陣列,同理:

data4[[3, 3, 1, 2, 0], [2, 1, 2, 0, 3], [2, 2, 0, 2, 1]]即為座標(3,2,2)、(3,1,2)、(1,2,0)、(2,0,2)、(0,3,1)的元素

2.3神奇索引發揮類似切片功能

切片是逗號分隔,在每一維上可用一維資料索引陣列作為其索引

多個索引陣列其實就是一種特殊的切片,每維索引都是一個一維資料索引

例:

data3 = np.arange(32).reshape((8, 4))
print(data3)
kols = data3[[1, 5, 7, 2]]
print('-'*20 + 'kols' + '-'*20)
print(kols)
print('-'*20 + 'data3[[1, 5, 7, 2]][:, [0, 3, 1, 2, 3]]' + '-'*20)
print(data3[[1, 5, 7, 2]][:, [0, 3, 1, 2, 3]])

輸出為:

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]
 [20 21 22 23]
 [24 25 26 27]
 [28 29 30 31]]
--------------------kols--------------------
[[ 4  5  6  7]
 [20 21 22 23]
 [28 29 30 31]
 [ 8  9 10 11]]
--------------------data3[[1, 5, 7, 2]][:, [0, 3, 1, 2, 3]]--------------------
[[ 4  7  5  6  7]
 [20 23 21 22 23]
 [28 31 29 30 31]
 [ 8 11  9 10 11]]

data3[[1, 5, 7, 2]][:, [0, 3, 1, 2]]其實就是data3[[1, 5, 7, 2]],即kols的切片,切片第一維取全部,即全部行。

第二維取一維資料陣列[0,3,1,2]即:

新陣列第一列為kols第一列(0)[4 20 28 8]

第二列為kols第4列(3)[7 23 31 11]

第三列為kols第2列(1)[5 21 29 9]

第四列為kols第3列(2)[6 22 30 10]

第五列為kols第4列(3)[7 23 31 11]