NumPy中的累积计数,无需迭代 [英] Cumulative counts in NumPy without iteration
问题描述
我有一个像这样的数组:
I have an array like so:
a = np.array([0.1, 0.2, 1.0, 1.0, 1.0, 0.9, 0.6, 1.0, 0.0, 1.0])
我希望有一个实例为1.0 的运行计数器,当它遇到0.0时会重置,因此结果将是:
I'd like to have a running counter of instances of 1.0 that resets when it encounters a 0.0, so the result would be:
[0, 0, 1, 2, 3, 3, 3, 4, 0, 1]
我最初的想法是使用类似b = np.cumsum(a [a == 1.0])的方法,但是我不知道如何(1)对此进行修改以将其重置为零,或者(2)对其进行结构化,以便输出数组与输入数组具有相同的形状.有没有想法如何做到这一点而无需迭代?
My initial thought was to use something like b = np.cumsum(a[a==1.0]), but I don't know how to (1) modify this to reset at zeros or (2) quite how to structure it so the output array is the same shape as the input array. Any ideas how to do this without iteration?
推荐答案
我认为您可以做类似的事情
I think you could do something like
def rcount(a):
without_reset = (a == 1).cumsum()
reset_at = (a == 0)
overcount = np.maximum.accumulate(without_reset * reset_at)
result = without_reset - overcount
return result
这给了我
>>> a = np.array([0.1, 0.2, 1.0, 1.0, 1.0, 0.9, 0.6, 1.0, 0.0, 1.0])
>>> rcount(a)
array([0, 0, 1, 2, 3, 3, 3, 4, 0, 1])
之所以可行,是因为我们可以使用累积最大值来计算超额":
This works because we can use the cumulative maximum to figure out the "overcount":
>>> without_reset * reset_at
array([0, 0, 0, 0, 0, 0, 0, 0, 4, 0])
>>> np.maximum.accumulate(without_reset * reset_at)
array([0, 0, 0, 0, 0, 0, 0, 0, 4, 4])
健全性测试:
Sanity testing:
def manual(arr):
out = []
count = 0
for x in arr:
if x == 1:
count += 1
if x == 0:
count = 0
out.append(count)
return out
def test():
for w in [1, 2, 10, 10**4]:
for trial in range(100):
for vals in [0,1],[0,1,2]:
b = np.random.choice(vals, size=w)
assert (rcount(b) == manual(b)).all()
print("hooray!")
然后
>>> test()
hooray!
这篇关于NumPy中的累积计数,无需迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!