简体   繁体   English

总结numpy数组中的非零元素

[英]Summing up non-zero elements in numpy array

I would like to sum up non-zero elements of an array (1-d) but do it separately for positive and negative integers (they can only be ones and two) and also display zeros where they are.我想总结一个数组(1-d)的非零元素,但分别对正整数和负整数(它们只能是一和二)进行总结,并在它们所在的位置显示零。

An example of an array:数组示例:

array = np.array([0, 0, 0, -1, -1, 0, 1, 2, 1, 1, 0, -1, 0, 1, 1, -1, -2])

Output:输出:

array([0, 0, 0, -2, 0, 5, 0, -1, 0, 2, -3])

I think my problem is that I have no idea how to separate the sequences of positive and negative values in array.我认为我的问题是我不知道如何将数组中的正值和负值序列分开。

Here's one way -这是一种方法 -

def sum_by_signs(a):
    m1 = a<0
    m2 = a>0
    m0 = a==0 # or ~m1 & ~m2
    p = np.flatnonzero(m0[:-1] | np.diff(m1) | np.diff(m2))+1
    return np.add.reduceat(a, np.r_[0,p])

Or bring that np.r_[0 part into boolean construction part -或者将np.r_[0部分带np.r_[0构造部分 -

def sum_by_signs_v2(a):
    m1 = a<0
    m2 = a>0
    m0 = a==0 # or ~m1 & ~m2
    p = np.flatnonzero(np.r_[True, m0[:-1] | np.diff(m1) | np.diff(m2)])
    return np.add.reduceat(a, p)

Explanation解释

We are starting off the idea to split the array into "islands" based on sign changes or when we encounter a sequence of 0s, in which case we are looking to split each element as a separate one.我们开始考虑根据符号变化或当我们遇到一系列 0 时将数组拆分为“孤岛”,在这种情况下,我们希望将每个元素拆分为一个单独的元素。 By splitting, think of it as list of lists, if that makes it easier to understand.通过拆分,将其视为列表列表,如果这样更容易理解的话。 Now, the game is how do we get those splits.现在,游戏是我们如何获得这些分裂。 We need indices that signifies the start, stop indices of those islands.我们需要表示这些岛的开始、停止索引的索引。 As said earlier, there are three cases, sign changes from + to - or vice versa or sequence of 0s.如前所述,存在三种情况,符号从+变为-或反之亦然或序列为 0。

Hence, that structure of boolean masks are used to give those indices with one-off slices to detect sign changes from + to - and vice versa with a combination of np.diff(m1) | np.diff(m2)因此,布尔掩码的结构用于为这些索引提供一次性切片,以检测从+-符号变化,反之亦然,结合np.diff(m1) | np.diff(m2) np.diff(m1) | np.diff(m2) . np.diff(m1) | np.diff(m2) Final one of m0[:-1] is for sequence of 0s . m0[:-1]最后一个是0s序列。 These indices are then fed to np.add.reduceat to get intervaled summations.然后将这些索引输入np.add.reduceat以获得间隔求和。

Sample runs -样品运行 -

In [208]: a
Out[208]: array([ 0,  0,  0, -1, -1,  0,  1,  2,  1,  1,  0, -1,  0,  1,  1, -1, -2])

In [209]: sum_by_signs(a)
Out[209]: array([ 0,  0,  0, -2,  0,  5,  0, -1,  0,  2, -3])

In [211]: a
Out[211]: array([ 1,  2,  0, -1, -1,  0,  1,  2,  1,  1,  0, -1,  0,  1,  1, -1, -2])

In [212]: sum_by_signs(a)
Out[212]: array([ 3,  0, -2,  0,  5,  0, -1,  0,  2, -3])

In [214]: a
Out[214]: 
array([ 1,  2,  0, -1, -1,  0,  1,  2,  1,  1,  0, -1,  0,  1,  1, -1, -2,
        0])

In [215]: sum_by_signs(a)
Out[215]: array([ 3,  0, -2,  0,  5,  0, -1,  0,  2, -3,  0])

This solves the problem, but surely theres a smarter way to do it这解决了问题,但肯定有更聪明的方法来做到这一点

array = [0, 0, 0, -1, -1, 0, 1, 2, 1, 1, 0, -1, 0, 1, 1, -1, -2]

switch = 0
while switch == 0:
    for i in range(len(array)):
        try:
            array[i+1]
            if array[i] > 0 and array[i+1] > 0: 
                array[i] += array[i + 1]
                array.pop(i + 1)
                break
            elif array[i] < 0 and array[i+1] < 0:   
                array[i] += array[i + 1]
                array.pop(i + 1)
                break
        except:
            switch = 1
            break

at the end, the value of array is [0, 0, 0, -2, 0, 5, 0, -1, 0, 2, -3]最后,数组的值为 [0, 0, 0, -2, 0, 5, 0, -1, 0, 2, -3]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM