仅对python数组中的连续值求和

hur*_*ght 6 python arrays numpy

我是python的新手(甚至编程!),所以我会尽可能清楚地解释我的问题.对你们来说这很容易,但我还没有找到满意的结果.

这是问题所在:

我有一个包含负值和正值的数组,比如说:

x = numpy.array([1, 4, 2, 3, -1, -6, -6, 5, 6, 7, 3, 1, -5, 4, 9, -5, -2, -1, -4])
Run Code Online (Sandbox Code Playgroud)

我想总结仅那些值连续,即,仅总和(-1,-6,-6),总和(-5,-2,-1,-4)等.我已经尝试使用numpy.where,以及基于条件的numpy.split.

例如:

 for i in range(len(x)):
     if x[i] < 0.:
         y[i] = sum(x[i])
Run Code Online (Sandbox Code Playgroud)

但是,正如您所料,我只是得到了数组中所有负值的总和.在这种情况下, sum(-1,-6,-6,-5,-5,-2,-1,-4)可以和我分享一个美学和有效的方法来解决这个问题吗?我将不胜感激.

非常感谢你

Kas*_*mvd 7

您可以使用itertools模块,在这里使用groupby您可以根据这些符号对项目进行分组,然后检查它是否符合key函数中的条件,因此它包含负数,然后产生总和,然后产生它,最后您可以使用chain.from_iterable函数链接结果:

>>> from itertools import groupby,tee,chain
>>> def summ_neg(li):
...     for k,g in groupby(li,key=lambda i:i<0) :
...           if k:
...              yield [sum(g)]
...           yield g
... 
>>> list(chain.from_iterable(summ_neg(x)))
[1, 4, 2, 3, -13, 5, 6, 7, 3, 1, -5, 4, 9, -12]
Run Code Online (Sandbox Code Playgroud)

或者作为更加pythonic的方式使用列表理解:

 list(chain.from_iterable([[sum(g)] if k else list(g) for k,g in groupby(x,key=lambda i:i<0)]))
[1, 4, 2, 3, -13, 5, 6, 7, 3, 1, -5, 4, 9, -12]
Run Code Online (Sandbox Code Playgroud)


Div*_*kar 1

这是一个矢量化的 NumPythonic 解决方案 -

# Mask of negative numbers
mask = x<0

# Differentiation between Consecutive mask elements. We would look for 
# 1s and -1s to detect rising and falling edges in the mask corresponding 
# to the islands of negative numbers.
diffs = np.diff(mask.astype(int))

# Mask with 1s at start of negative islands
start_mask = np.append(True,diffs==1) 

# Mask of negative numbers with islands of one isolated negative numbers removed
mask1 = mask & ~(start_mask & np.append(diffs==-1,True))

# ID array for IDing islands of negative numbers
id = (start_mask & mask1).cumsum()

# Finally use bincount to sum elements within their own IDs
out = np.bincount(id[mask1]-1,x[mask1])
Run Code Online (Sandbox Code Playgroud)

您还可以使用np.convolveget mask1,就像这样 -

mask1 = np.convolve(mask.astype(int),np.ones(3),'same')>1
Run Code Online (Sandbox Code Playgroud)

您还可以通过对现有代码进行一些调整来获取每个“岛”中负数的计数 -

counts = np.bincount(id[mask1]-1)
Run Code Online (Sandbox Code Playgroud)

样本运行 -

In [395]: x
Out[395]: 
array([ 1,  4,  2,  3, -1, -6, -6,  5,  6,  7,  3,  1, -5,  4,  9, -5, -2,
       -1, -4])

In [396]: out
Out[396]: array([-13., -12.])

In [397]: counts
Out[397]: array([3, 4])
Run Code Online (Sandbox Code Playgroud)

  • @hurrdrought 太棒了!我认为这个解决方案在性能方面是高效的,因为它避免了循环,这就是基于 NumPy 的解决方案的亮点。您是否也能够为您的数据集计算这些方法的时间? (2认同)