簡體   English   中英

“子數組”作為 numpy.where() 的條件

[英]'Subarray' as condition to numpy.where()

事先說清楚:我對 python 比較陌生,我的“編程技能”主要圍繞 MATLAB(這意味着我可以使用內置函數)。 因此,我希望我的問題沒有我想的那么愚蠢。 我還沒有找到答案意味着我自己不理解我的問題,或者它確實是“新事物”。

玩笑夠了:我已經從圖像中提取了一個數組,其中我已經沿着我預先從圖像中確定的回歸線存儲了像素值,留下了一個像[0,0,0,...,0,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1,...]這樣的 numpy 數組[0,0,0,...,0,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1,...] 由於一些噪音,我在數組中得到了一些意外的噪音,導致了我的問題:我想找到第一個值的索引,然后我可以找到子數組[1,1,1,1,1]例如。 我似乎無法讓numpy.where()做到這一點,我必須承認我完全不知道如何讓它有效地工作。 使用循環手動搜索子數組不夠有效,因此使用蠻力對我也不起作用。

有沒有辦法以“pythonic”的方式解決這個問題? 如果是這樣,您能否提供或多或少的詳細解釋,以便我理解和復制它? 我想考慮更多的“pythonic”,但我似乎無法進入 python 思維模式。

使用np.cumsum()並將元素 5 索引之間的差異分開。

import numpy as np
np.random.seed(456)  # Make results repeatable

arr= np.random.randint(2, size=100)

arr
# array([1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1,
#        1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1,
#        0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1,
#        1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0,
#        1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1])

cumulate = np.zeros(arr.shape[0]+1, dtype = np.int)
cumulate[1:] = arr.cumsum()   # First item in the array must be zero
diff = cumulate[5:]-cumulate[:-5]

cumulate
# array([ 0, 1,  2,  3,  4,  4,  5,  5,  5,  6,  6,  6,  7,  7,  8,  9,  9, 10,
#        11, 12, 12, 13, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17,
#        17, 17, 18, 18, 18, 18, 18, 19, 19, 20, 20, 20, 21, 22, 23, 24, 25,
#        25, 25, 26, 26, 27, 27, 28, 28, 28, 29, 30, 30, 30, 30, 31, 32, 33,
#        34, 35, 36, 36, 36, 37, 38, 38, 38, 39, 39, 40, 41, 42, 42, 42, 42,
#        43, 44, 44, 45, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 52])

np.where( diff == 5 )
# (array([46, 65, 66]),)

np.where 返回一個數組元組,因此 [0][0] 以獲得所需的索引。

np.where(diff == 5)[0][0]
# 46

np.cumsum僅提供針對此問題的解決方案; 我將嘗試針對任何類型的模式提出更通用的解決方案。 您可以嘗試將其視為一種字符串匹配問題。 您有一個大字符串(例如,您的 1 和 0 數組)和一個要查找的特定噪聲,即 11111。此外,您希望找到該模式首次出現的索引。 這可以通過多種方式在一行代碼中輕松完成。

import re

def find_idx_of_first_noise(A, N):
    return re.search(''.join(N.astype(str)),''.join(A.astype(str))).start()

A = np.array([0,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1])
N = np.array([1,1,1,1,1])

print(find_idx_of_first_noise(A, noise))

出去:

7

A 和 N 是 numpy 整數數組,因此我將它們轉換為帶有.astype(str)的字符串數組。 然后我通過調用''.join()將整個字符串數組連接成一個字符串。 因此,我有效地運行了以下行: re.search('11111','0100100111111111').start() ,它在 A 中找到 11111,並給我它第一次出現的索引。

您應該掌握的另一種編寫代碼的 Pythonic 方法是列表推導式。 我將在一行代碼中再次執行上述任務:

print([i for i in range(len(A)-len(N)+1) if (A[i:i+len(N)]==N).all()][0])

出去:

7

盡管方便,列表推導式仍然是一種蠻力方法; 它基本上是一個列表中的 for 循環。

現在我認為最快和最pythonic的方法是使用tostring。

print(A.tostring().index(N.tostring())//A.itemsize)

出去:

7

將 numpy 數組轉換為字節字符串,然后使用.index找到您擁有的任何模式/噪音的位置。 除以 A 中項目的大小,您就得到了結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM