簡體   English   中英

在python數組中查找沒有子集的唯一集

[英]Finding unique sets without subsets in python array

我有一個數據集,需要輸出布爾樣式數據,無論是true還是true,僅輸出1和0。 我試圖解析經過處理的簡單數據集,以在numpy數組中查找信息的子集,該數組在一個方向上大約100,000個元素,在另一個方向上大約20個元素。 我只需要沿20軸進行搜索,但是我需要對100,000個條目中的每個條目進行搜索,並獲取可以映射的輸出。

我制作了一個由零組成的大小的數組,目的是簡單地將匹配的索引指示符標記為1。主要的障礙是,如果我找到一個長集(我正在處理長集到小集) ),則無需包含其中的任何較小的集合。

樣本:[0,0,1,1,1,1,1,0,0,1,1,1,0,0,0,1,0,1]

我需要在這里找到從索引2開始有1組5,從索引9開始有3的一組,並且不返回5組的任何子集,就好像它是4組或一組3的結果,因此保留所有已經覆蓋的值的結果。 例如,對於3組,索引2、3、4、5和6都將保持零。 它不需要太高效,我不在乎它是否仍在搜索,我只需要保留結果即可。

目前,我正在使用基本上像這樣的代碼塊進行簡單搜索:

values = numpy.array([0,1,1,1,1,1,0,0,1,1,1])
searchval = [1,2]
N = len(searchval)
possibles = numpy.where(values == searchval[0])[0]
print(possibles)
solns = []
for p in possibles:
    check = values[p:p+N]
    if numpy.all(check == searchval):
        solns.append(p)
print(solns)

我一直在絞盡腦汁,想出一種方法來重組此代碼或類似代碼以產生期望的結果。 最終目標是搜索9到3的組,並有效地使用1s和0s的矩陣來指示索引是否有一個我們想要的起始組。

希望有人可以指出我要完成這項工作所缺少的內容。 謝謝!

像這樣嗎

from collections import defaultdict

sample = [0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1]

# Keys are number of consecutive 1's, values are indicies
results = defaultdict(list)
found = 0

for i, x in enumerate(samples):
    if x == 1:
        found += 1
    elif i == 0 or found == 0:
        continue
    else:
        results[found].append(i - found)
        found = 0

if found:
    results[found].append(i - found + 1)

assert results == {1: [15, 17], 3: [9], 5: [2]}

使用more_itertools ,一個第三方庫( pip install more_itertools ):

import more_itertools as mit


sample = [0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1]

groups = [list(c) for c in mit.consecutive_groups((mit.locate(sample)))]
d = {group[0]: len(group) for group in groups}
d
# {2: 5, 9: 3, 15: 1, 17: 1}

該結果顯示為“索引2是5個一組。索引9是3個一組,等等”。


細節

作為字典 ,您可以提取各種信息:

>>> # List of starting indices
>>> list(d)
[2, 9, 15, 17]

>>> # List indices for all lonely groups
>>> [k for k, v in d.items() if v == 1]
[15, 17]

>>> # List indices of groups greater the 2 items
>>> [k for k, v in d.items() if v > 1]
[2, 9]

這是一個numpy的解決方案。 我使用一個小示例進行演示,但是它很容易擴展(在我比較適中的筆記本電腦上, 20 x 100,000需要25毫秒,請參閱本文結尾處的計時):

>>> import numpy as np
>>> 
>>> 
>>> a = np.random.randint(0, 2, (5, 10), dtype=np.int8)
>>> a
array([[0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
       [0, 1, 1, 0, 1, 0, 1, 0, 0, 0],
       [1, 0, 1, 1, 1, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
       [0, 0, 1, 0, 1, 1, 1, 1, 0, 0]], dtype=int8)
>>> 
>>> padded = np.pad(a,((1,1),(0,0)), 'constant')
# compare array to itself with offset to mark all switches from
# 0 to 1 or from 1 to 0
# then use 'where' to extract the coordinates
>>> colinds, rowinds = np.where((padded[:-1] != padded[1:]).T)
>>> 
# the lengths of sets are the differences between switch points
>>> lengths = rowinds[1::2] - rowinds[::2]
# now we have the lengths we are free to throw the off-switches away
>>> colinds, rowinds = colinds[::2], rowinds[::2]
>>> 
# admire
>>> from pprint import pprint
>>> pprint(list(zip(colinds, rowinds, lengths)))
[(0, 2, 1),
 (1, 0, 2),
 (2, 1, 2),
 (2, 4, 1),
 (3, 2, 1),
 (4, 0, 5),
 (5, 0, 1),
 (5, 2, 1),
 (5, 4, 1),
 (6, 1, 1),
 (6, 3, 2),
 (7, 4, 1)]

時序:

>>> def find_stretches(a):
...     padded = np.pad(a,((1,1),(0,0)), 'constant')
...     colinds, rowinds = np.where((padded[:-1] != padded[1:]).T)
...     lengths = rowinds[1::2] - rowinds[::2]
...     colinds, rowinds = colinds[::2], rowinds[::2]
...     return colinds, rowinds, lengths
... 
>>> a = np.random.randint(0, 2, (20, 100000), dtype=np.int8)
>>> from timeit import repeat
>>> kwds = dict(globals=globals(), number=100)
>>> repeat('find_stretches(a)', **kwds)
[2.475784719004878, 2.4715258619980887, 2.4705517270049313]

暫無
暫無

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

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