[英]Find indexes of repeated elements in an array (Python, NumPy)
假設,我有一個 NumPy 整數數組,如下所示:
[34,2,3,22,22,22,22,22,22,18,90,5,-55,-19,22,6,6,6,6,6,6,6,6,23,53,1,5,-42,82]
我想找到數組的開始和結束索引,其中一個值重復的次數超過 x 次(比如 5 次)。 所以在上面的例子中,它是值 22 和 6。重復 22 的開始索引是 3,結束索引是 8。重復 6 也是如此。Python 中是否有一個特殊的工具有用? 否則,我將遍歷索引的數組索引並將實際值與前一個值進行比較。
問候。
使用np.diff
和np.diff
在此處給出的方法來查找數組中的零運行:
import numpy as np
def zero_runs(a): # from link
iszero = np.concatenate(([0], np.equal(a, 0).view(np.int8), [0]))
absdiff = np.abs(np.diff(iszero))
ranges = np.where(absdiff == 1)[0].reshape(-1, 2)
return ranges
a = [34,2,3,22,22,22,22,22,22,18,90,5,-55,-19,22,6,6,6,6,6,6,6,6,23,53,1,5,-42,82]
zero_runs(np.diff(a))
Out[87]:
array([[ 3, 8],
[15, 22]], dtype=int32)
然后可以根據運行開始和結束之間的差異進行過濾:
runs = zero_runs(np.diff(a))
runs[runs[:, 1]-runs[:, 0]>5] # runs of 7 or more, to illustrate filter
Out[96]: array([[15, 22]], dtype=int32)
這真的沒有什么捷徑可走。 您可以執行以下操作:
mult = 5
for elem in val_list:
target = [elem] * mult
found_at = val_list.index(target)
我將未找到的異常和更長的序列檢測留給您。
這是使用 Python 的原生itertools
的解決方案。
代碼
import itertools as it
def find_ranges(lst, n=2):
"""Return ranges for `n` or more repeated values."""
groups = ((k, tuple(g)) for k, g in it.groupby(enumerate(lst), lambda x: x[-1]))
repeated = (idx_g for k, idx_g in groups if len(idx_g) >=n)
return ((sub[0][0], sub[-1][0]) for sub in repeated)
lst = [34,2,3,22,22,22,22,22,22,18,90,5,-55,-19,22,6,6,6,6,6,6,6,6,23,53,1,5,-42,82]
list(find_ranges(lst, 5))
# [(3, 8), (15, 22)]
測試
import nose.tools as nt
def test_ranges(f):
"""Verify list results identifying ranges."""
nt.eq_(list(f([])), [])
nt.eq_(list(f([0, 1,1,1,1,1,1, 2], 5)), [(1, 6)])
nt.eq_(list(f([1,1,1,1,1,1, 2,2, 1, 3, 1,1,1,1,1,1], 5)), [(0, 5), (10, 15)])
nt.eq_(list(f([1,1, 2, 1,1,1,1, 2, 1,1,1], 3)), [(3, 6), (8, 10)])
nt.eq_(list(f([1,1,1,1, 2, 1,1,1, 2, 1,1,1,1], 3)), [(0, 3), (5, 7), (9, 12)])
test_ranges(find_ranges)
此示例在lst
捕獲 (index, element) 對,然后按元素對它們進行分組。 只保留重復的對。 最后,第一對和最后一對被切片,從每個重復的組中產生(開始,結束)索引。
另請參閱此帖子以使用itertools.groupby
查找索引范圍。
如果您要在列表L
查找重復n
次的value
,您可以執行以下操作:
def find_repeat(value, n, L):
look_for = [value for _ in range(n)]
for i in range(len(L)):
if L[i] == value and L[i:i+n] == look_for:
return i, i+n
這是一個相對快速、無錯誤的解決方案,它還告訴您運行中的副本數。 其中一些代碼是從 KAL 的解決方案中借用的。
# Return the start and (1-past-the-end) indices of the first instance of
# at least min_count copies of element value in container l
def find_repeat(value, min_count, l):
look_for = [value for _ in range(min_count)]
for i in range(len(l)):
count = 0
while l[i + count] == value:
count += 1
if count >= min_count:
return i, i + count
我也有類似的需求。 這就是我想出的,僅使用理解列表:
A=[34,2,3,22,22,22,22,22,22,18,90,5,-55,-19,22,6,6,6,6,6,6,6,6,23,53,1,5,-42,82]
找到唯一的並返回它們的索引
_, ind = np.unique(A,return_index=True)
np.unique 對數組進行排序,對索引進行排序以按原始順序獲取索引
ind = np.sort(ind)
ind
包含重復組中第一個元素的索引,通過非連續索引可見它們的diff
給出了組中元素的數量。 使用np.diff(ind)>5
過濾將在組的起始索引處給出一個帶有True
的布爾數組。 ind
數組包含過濾列表中每個True
之后的每個組的結束索引
創建一個字典,以鍵作為重復元素,值作為該組的開始和結束索引的元組
rep_groups = dict((A[ind[i]], (ind[i], ind[i+1]-1)) for i,v in enumerate(np.diff(ind)>5) if v)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.