[英]'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.