numpy高階函式操作之——select、choose
一、什麼是np.select()
顧名思義,這個函式用用來“ 根據某一些條件 ” 來篩選出 “某一些元素 ”的函式,比如我有一個數組,我如果用if-else語句去做,當然也可以,比如我們讓小於6的元素各自加上10,大於等於6的元素統統變為100,我們可以這麼做,程式碼如下:
a=np.array([1,2,3,4,5,6,7,8,9,10])
aaa=[] #儲存篩選結果的列表
for i in a: #通過迴圈去完成
if(i<6):
i=i+10
else:
i=100
aaa.append(i)
print(aaa)
執行結果為 [11, 12, 13, 14, 15, 100, 100, 100, 100, 100]
但是這樣做的缺點就是效率太過於低下,因為這樣做就是使用迴圈,條件判斷去完成,select()函式就是專門針對這種情況提出來的。
1、select函式的定義
def select(condlist, choicelist, default=0):
condlist引數:操作資料所依據的條件
choicelist引數:根據condlist條件,索要執行的操作
返回值:返回的是一個“ 列表” 。
注意上面的condlist和choicelist都必須是寫成“ 列表 ”的形式。
要實現上面同樣的操作,這裡只需要一句話就可以完成
a=np.array([1,2,3,4,5,6,7,8,9,10])
condlist=[a<6] #第一個引數,必須用【】括起來,列表形式
print(condlist)
choicelist=[a+10] #第二個引數,必須用【】括起來,列表形式
print(choicelist)
aa=np.select(condlist,choicelist,default=100)
print(aa)
程式執行的結果為:
[array([ True, True, True, True, True, False, False, False, False,False])]
[array([11, 12, 13, 14, 15, 16, 17, 18, 19, 20])]
[11 12 13 14 15 100 100 100 100 100] #由此可見,依然得到的是上面的結果。
什麼意思呢?可以這樣理解,對於第一個引數condlist=[ a<6 ],我們將a<6看成是一個條件,只不過這個條件是針對array型別的a的,第二個引數choicelist所要執行的操作是依據condlist而言的,即這裡的 [a+10]裡面的a+10這個操作,和 [a<6]這個裡面的,a<6是對應關係的,即當第一條件裡的每個元素滿足條件的時候,即為True的時候,就執行相應的操作,如果為false,那麼久不執行,而對於不滿足的元素,則執行預設的值,即default。
2、select() 對於多條件、多操作的篩選和執行
比如針對一個數組,我們規定小於6的就加上10,介於10~15之間的就平方,大於20的就乘以10,其他的就預設變為100.
a=np.array([[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]])
condlist=[a<6,np.logical_and(a>10,a<16),a>20] #引數一,定義三個限制條件
print(condlist)
choicelist=[a+10,a**2,a*10] #引數二,定義三個不同的操作
print(choicelist)
aa=np.select(condlist,choicelist)
print(aa)
print('=======================================')
執行結果為:
[[ 11 12 13 14 15] #第一行分別加上了10
[ 0 0 0 0 0]
[121 144 169 196 225] #第三行每個數分別進行了平方
[ 0 0 0 0 0]
[210 220 230 240 250]] #第五行每個數分別乘以10
3、select函式總結
引數一,condlist=【條件一,條件二,條件三,,,,】
引數二,choicelist=【操作一,操作二,操作三,,,,,】
只有每個條件中,對應為true的才會執行相對應的操作,最終所有條件都不滿足的元素,則執行預設值default。
二、np.choose()函式
choose()函式,顧名思義,也是通過某一些條件去“選擇”相關的元素,choose的操作會比自己使用for-if-else效率要高。
1、choose()函式的定義
def choose(a, choices, out=None, mode='raise'):
引數 a :它必須是一個 int 型的 陣列,並且 a 中的元素,必須是0~n-1之間的數,這裡的n表示的就是陣列choices陣列最外層的維度數。
choices:表示的是要操作的陣列,要注意的是choices的陣列的維度是一定要和a進行匹配的,如果匹配不了,會出現錯誤。
引數out:接收運算結果的陣列,它的維度一定要和 a 是一樣的,是可選引數。
引數mode:預設的是raise,表示的是a陣列中的元素不能超過 n ,她還有兩個可選值,
clip:將 a 中的 元素 如果小於0,則將其變為0,如果大於n-1,則變為n-1
wrap:將a中的值 value變為value mod n,即值除以n的餘數。
2、choose的應用
(1)當a和choices都是相同維數的時候——a為1維,choices為1維
result=np.array([0,0,0,0,0])
aa=np.choose([4,2,1,3,0],[11,22,33,44,55],out=result) #當a,與choices的尾數相同的時候
print(aa)
print(result) #result是out輸出的,這裡和aa的結果是一樣的
執行結果:
[55 33 22 44 11]
[55 33 22 44 11] #二者的結果是一樣的,這個地方使用了out,mode引數使用的是預設值
總結:因為choices的 n 為5,所以 a 中的元素不能夠超過5 ,它代表的是 choices中的 索引index。11對應0,22對應1,33對應2,44對應3,55對應4.
(2)當a的維數比choices的維數多的時候——a為2維,choices為1維
bb=np.choose([[4,2,1,3,0],[3,4,2,0,1],[0,2,1,4,3]],[11,22,33,44,55])
print(bb)
執行結果為:
[[55 33 22 44 11]
[44 55 33 11 22]
[11 33 22 55 44]] # a 中的每一個索引 都分別與choices 對應著的。
(3)當a的維數比choices的維數少的時候——a為1維,choices為2維
cc=np.choose([4,2,1,3,0],[[11,22,33,32,31],[44,55,66,65,64],[77,88,99,98,97],[111,222,333,332,331],[444,555,666,665,664]])
print(cc)
執行結果為:
[444 88 66 332 31] # 444 對應於 choices[4,0],88對應於 choices[2,1],66 對應於 choices[1,2],332 對應於 choices [3,3],31 對應於 choices[0,4]
總結:由此可知,choices的最外層索引index依然是與a進行匹配的,但是內層索引是按照從0開始,0、1、2、3、4逐漸遞增的。鑑於此,choices的內層元素數量依然要與a的個數進行匹配才行,否則會報錯。
(4)當a的維數和choices的維數都是多維的時候——a為2維,choices為2維
dd=np.choose([[4,2,1,3,0],[3,4,2,0,1],[0,2,1,4,3]],[[11,22,33,32,31],[44,55,66,65,64],[77,88,99,98,97],[111,222,333,332,331],[444,555,666,665,664]])
print(dd)
執行結果為:
[[444 88 66 332 31]
[111 555 99 32 64]
[ 11 88 66 665 331]] #運算過程同上面的 (3)是類似的
總結:從上面的幾個例子可以看出,choose最終的輸出結果是和 a 一樣的。a中的數值不能超過choices的索引值,但是沒有要求一定要a和choices維度相同。
3、choose的綜合應用
a=[[1,0,2],[2,1,0],[2,0,1]]
c1=[[1,2,3],[4,5,6],[7,8,9]]
c2=[[11,22,33],[44,55,66],[77,88,99]]
choices=[c1,100,c2]
result=np.choose(a,choices)
print(result)
執行結果為:
[[100 2 33]
[ 44 100 6]
[ 77 8 100]] #原理同上
再例如:
a = [[1, 0, 1], [0, 1, 0], [1, 0, 1]]
choices = [-10, 10]
result=np.choose(a, choices)
print(result)
結果為:
[[ 10, -10, 10],
[-10, 10, -10],
[ 10, -10, 10]]