Numpy数组中特定真/假排序的出现次数计数

2024-06-17 13:11:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含真值和假值的Numpy数组,比如:

test = np.array([False, False, False, True, False, True, False, True, False,False, False, False, True, True, False, True])

我想知道以下模式(False,True,False)在数组中发生的次数。在上面的测试中是4。这并不是唯一的模式,但是我假设当我理解了这个代码时,我也可以创建其他的模式。你知道吗

当然,我可以在数组上循环。如果第一个值相等,则比较下一个值,否则转到循环中的下一个值。像这样:

totalTimes=0
def swapToBegin(x):
    if(x>=len(test)):
        x-=len(test)
    return(x)
for i in range(len(test)):
    if(test[i]==False):
        if(test[swapToBegin(i+1)]==True):
            if test[swapToBegin(i+2)]==False:
                totalTimes += 1

但是,由于我需要这样做很多次,这段代码将非常缓慢。小的改进是可以做的,因为这是非常迅速地表明我需要什么。但必须有更好的解决办法。你知道吗

有没有更好的方法来搜索数组中的模式?它不需要合并数组的结尾和开头,因为我以后可以这样做。但如果能包括在内那就太好了。你知道吗


Tags: 代码testnumpyfalsetruelenifnp
2条回答

您还没有给出任何关于test有多大的细节,所以对于我使用的方法的基准测试,它有1000个元素。下一个重要部分是实际分析代码。你不能说它慢(或快),直到有硬数字支持它。你的代码在我的电脑上运行大约1.49毫秒。你知道吗

通常可以通过移除python循环并用numpy函数替换它们来改进numpy。 因此,我没有单独测试每个元素(大量的if条件可能会减慢速度),而是将其全部放入一个数组比较中,然后使用all检查每个元素是否匹配。你知道吗

check = array([False, True, False])
sum([(test[i:i+3]==check).all() for i in range(len(test) - 2)])

分析结果显示它的运行时间为1.91毫秒

这实际上是一种倒退。那么,是什么导致了经济放缓呢?嗯,使用[]访问数组会创建一个新的数组对象,它可能是数组的一部分。更好的方法可能是创建一个具有偏移量的大数组,然后使用广播进行比较。你知道吗

sum((c_[test[:-2], test[1:-1], test[2:]] == check).all(1))

这次check与数组的每一行c_[test[:-2], test[1:-1], test[2:]]进行比较。all的axis参数(1)仅用于计算每个元素匹配的行。它运行在40.1美元。这是一个巨大的进步。你知道吗

当然,创建要广播的数组要花费大量的成本来复制元素。为什么不直接比较呢?你知道吗

sum(all([test[i:len(test)-2+i]==v for i, v in enumerate(check)], 0))

这是18.7美元。你知道吗

最后一个加速的方法是使用as_strided。这是一个高级技巧,可以改变数组的步长以获得偏移数组,而无需复制任何数据。这通常是不值得的努力,但我把它包括在这里只是为了好玩。你知道吗

sum((np.lib.index_tricks.as_strided(test, (len(test) - len(check) + 1, len(check)), test.strides + (1, )) == check).all(1))

这也运行在大约40us。所以,在这种情况下,额外的努力不会增加任何东西。你知道吗

您可以使用包含[False,True,False]的数组来搜索它。你知道吗

searchfor = np.array([False, True, False])

相关问题 更多 >