统计numpy数组中值的连续出现次数,长度不定

28 投票
5 回答
21136 浏览
提问于 2025-04-18 10:36

假设我有一堆数字放在一个numpy数组里,我根据某个条件来测试这些数字,结果会得到一个布尔数组,也就是只包含真(True)和假(False)的数组:

np.random.seed(3456)
a = np.random.rand(8)
condition = a>0.5

接下来,我想用这个布尔数组来计算连续出现的真值(True)的长度。例如,如果我有一个数组[True,True,True,False,False,True,True,False,True],我希望得到的结果是[3,2,1],意思是连续的真值分别出现了3次、2次和1次。

我可以用以下代码来实现这个功能:

length,count = [],0
for i in range(len(condition)):

    if condition[i]==True:
        count += 1
    elif condition[i]==False and count>0:
        length.append(count)
        count = 0

    if i==len(condition)-1 and count>0:
        length.append(count)

    print length

不过,是否已经有现成的函数可以用来计算列表或数组中连续出现的元素的长度呢?比如在python、numpy、scipy等库里?

5 个回答

0

如果 t 是一个按升序排列的 numpy 数组,那么:

d=np.diff(t)
d_incr = np.argwhere(d>0).flatten()
d_incr = np.insert(d_incr, 0, 0)

这个 np 数组 d_incr 会包含发生变化的索引,这样你就可以对 d_incr[i-1] 和 d_incr[i] 之间的值进行操作,i 的范围是从 1 到 d_incr 的大小。

3
np.unique((~arr).cumsum()[arr], return_counts=True)[1]

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

3

你还可以通过查看条件数组的反转结果(用 np.where 得到的索引)来计算连续的 False 值之间的距离。关键是要确保布尔数组的开头是 False。简单来说,你是在计算 True 条件之间的边界距离。

condition = np.array([True, True, True, False, False, True, True, False, True, False])
if condition[0]:
    condition = np.concatenate([[False], condition])

idx = np.where(~condition)[0]

在最后一步,你需要从这些值中减去 1,这样就去掉了左右两边的边界。

>>> np.ediff1d(idx) - 1
array([3, 0, 2, 1])
57

如果你已经有了一个numpy数组,这种方法可能会更快:

>>> condition = np.array([True,True,True,False,False,True,True,False,True])
>>> np.diff(np.where(np.concatenate(([condition[0]],
                                     condition[:-1] != condition[1:],
                                     [True])))[0])[::2]
array([3, 2, 1])

它会找出每一段的开始位置,并对第一段和最后一段进行一些特别处理,然后简单地计算这些段开始位置之间的差值,同时忽略那些标记为False的段的长度。

22

这里有一个使用 itertools 的解决方案(可能不是最快的办法):

import itertools
condition = [True,True,True,False,False,True,True,False,True]
[ sum( 1 for _ in group ) for key, group in itertools.groupby( condition ) if key ]

Out:
[3, 2, 1]

撰写回答