【Python】numpy數組索引

numpy數組索引是一個大話題,有很多種方式可以讓你選中數據中的子集或者某個元素。主要有以下四種方式:
在這裏插入圖片描述

一,基礎索引

在一維數組中,你可以使用中括號指定索引獲取第i個值(從0開始計數),但是對於多維的數組,每個索引值對應的元素不再是一個數值,例如,在一個二維數組中,將得到一個以爲數組。單個元素可以繼續索引,或者傳遞一個索引的列表選擇單個元素。

import numpy as np
arr = np.arange(9).reshape((3,3))
arr[0]  # array([0, 1, 2])
arr[0][0]  # 0
arr[0,0]   # 0

這種方式獲取的數據爲原數組的視圖,對於視圖數值的修改,也會修改原數組數值。

二·,切片索引

numpy切片與Python列表的標準切片語法相同,通過切片可以靈活地得到一個子數組。與基礎索引一樣,切片索引也是原數組的視圖,修改數據也會作用於原數組。

arr[:2,1:]
"""
array([[1, 2],
       [4, 5]])
"""

切片索引有兩個實用的應用:
1,獲取數組的單行或者單列。

arr[0,:]  # array([0, 1, 2]) 獲取第1行
arr[:,0]  # array([0, 3, 6]) 獲取第1列

2,數組的逆序。

arr[::-1,::-1]   # 對整個數組進行逆序
"""
array([[6, 7, 8],
       [3, 4, 5],
       [0, 1, 2]])
"""
arr[::-1,:]   #行逆序
"""
array([[6, 7, 8],
       [3, 4, 5],
       [0, 1, 2]])
"""
arr[:,::-1]  # 列逆序
"""
array([[2, 1, 0],
       [5, 4, 3],
       [8, 7, 6]])
"""

三,布爾索引

布爾索引主要是利用的布爾數組,當數組的比較操作(比如==、>=)也是可以向量化,這些比較運算的結果是一個布爾數據類型的數組。該數組與原數組的長度和形狀都是一致,我們可以獲取到對應位置爲True的值。

bool_arr = arr>3
arr[bool_arr]   # array([4, 5, 6, 7, 8])

通過布爾索引獲得的子數組爲副本,修改後不影響原數組。

arr = np.array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
arr2 = arr[ arr>3]
arr2 = -1
arr
"""
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
"""

布爾數組操作

1,統計記錄個數
如果需要統計布爾數組中True的個數,可以使用np.count_nonzero函數

np.count_nonzero(arr>3) # 5

另一種方法是使用np.sum,False會被解釋爲0,而True被解釋爲1。sum()可以沿着行或列求和。

np.sum(arr>3)  # 5
#每一列中大於3的個數
np.sum(arr>3,axis=0)  # array([1, 2, 2])

2,快速地檢查是否包含True

np.all(arr>3)  # False   all 全部爲True時,返回True,否則返回False
np.any(arr>3)  # True    any 至少有一個爲True時,返回True,否則返回False
# np.all() 和 np.any()也可以沿着特定的軸。 
np.all(arr>7,axis=0)  # array([False, False, False])
np.any(arr>7,axis=0)   # array([False, False,  True])

3,python中的關鍵字and 和 or 對布爾數組不起作用,需要使用逐位邏輯運算符(&,|,^)
當使用 and 或者 or 時,就等於讓python將整個數組當作布爾對象;
當使用 & 或者 | 時,表達式操作的是數組中的元素,每個元素逐位運算。

# 每個元素逐位邏輯運算
a = np.array([1,0,1,1,0],dtype=bool)
b = np.array([1,0,1,1,0],dtype=bool)
a & b  # array([ True, False,  True,  True, False])
a = np.array([1,0,1,1,0],dtype=bool)
b = np.array([1,0,1,1,0],dtype=bool)
a and b 
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

a and b 之所以報錯,是因爲,無法知道a和b整個數組,分別是Ture還是False。沒法進行and運算,可以使用np.all() 或者 np.any()對整個數組進行判斷。

a = np.array([1,0,1,1,0],dtype=bool)
b = np.array([1,0,1,1,0],dtype=bool)
np.all(a) and np.any(b)  # False

四,數組索引

數組索引在概念上很簡單,通過一個數組來一次性獲取多個元素,

arr[[1,2]]
"""
array([[3, 4, 5],
       [6, 7, 8]])
"""
arr[[1,2],[0,1]]
# array([3, 7]) 分別獲取[1,0],[2,1]

在使用數組索引時,有兩個點需要注意:
1,使用數組索引,結果的形狀不是與被索引的數組的形狀一致。

arr.shape  # (3, 3)
ind = np.array([[0,2],[1,2]])    
arr[ind].shape  # (2, 2, 3)

2,操作重複的索引可以會產生一些出乎意料的結果。

x = np.zeros(10)
x[[0,0]] = [4,6]

上面的代碼執行後,x的結果爲array([6., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
這裏會有疑問,4去哪裏了?其實上面的代碼等同於賦值兩次。

A=1
A,A = 2,3
A  # 3 

A=2,然後A=3,所以最後結果爲3。

繼續設想以下操作:

x = np.zeros(10)
x[[0,0]] +=1
x[0]   # 1

按照之前的想法,x[0]的輸出結果應該的2,然而結果卻是1。x[[0,0]] +=1其實可以拆開爲:x[0],x[0] = x[0]+1,x[0]+1 ,換個簡單的例子:

a = 1
a,a=a+1,a+1
print("a="+str(a))

a的結果爲2,a,a=a+1,a+1的指向步驟是:
1,先計算等號右邊的結果,(2,2)
2,將右邊的結果賦給左邊:a=2,a=2。

在看一個例子:

a = 1
b = 2
a,a=b,a+b
print("a="+str(a))

a的結果爲3,a,a=b,a+b的指向步驟是:
1,先計算等號右邊的結果,(2,3)
2,將右邊的結果賦給左邊:a=2,a=3。

numpy數組索引真的是一個大話題,可以引申出許多東西的,還可以將四種方式混合使用,只要知道每種方式的特點,混合使用也不是問題。如有錯誤,歡迎留言指出。

參考:《Python數據科學手冊》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章