numpy中的按条件元素和

时间:2018-06-20 10:54:15

标签: python numpy

我找到了一种解决方案,可以累加前面的数字是否为负:

def func(x):
    for i, value in enumerate(x):
        if i == len(x)-1:
            break
        if value < 0:
            x[i+1] += value
    x = x.clip(min=0)
    return x

data = np.array([-3, 4, -2, -2, 6])
print(func(data))
>>>> [0 1 0 0 2]

有矢量化的numpy解决方案吗?这是一个非常小的数据样本,但是它将变得非常大,并且是二维的,例如:

data = np.array([[-3, 4, -2, -2, 6],[1, -2, -3, 7, 1]])

我想逐行应用。

2 个答案:

答案 0 :(得分:0)

广义上讲,矢量化依赖于以下事实:可以独立于所有其他元素来处理数组的许多元素,然后可以利用可一次应用于数组的所有元素的操作。但是,由于您的计算依赖于先前迭代的结果,因此需要线性遍历数据。

因此,可能无法完全向量化您的问题。但是由于每一行的计算都是彼此独立的,因此还有一些空间可以进行矢量化:这是一种解决方案,可以跨所有列进行矢量化,并且可以遍历所有行

def func(x):
    x = x.copy()
    for i in range(len(x) - 1):
        mask = x[i, ...] < 0
        x[i+1, mask, ...] += x[i, mask, ...]

    x = x.clip(min=0)
    return x

data = np.array([[-3, 4, -2, -2, 6],[1, -2, -3, 7, 1]])
func(data.T)
# array([[0, 1],
#        [1, 0],
#        [0, 0],
#        [0, 2],
#        [2, 1]])

我知道,您不想单独处理每一行,但是我选择交换两者,因为通常在数组的第一个维度上像这样进行迭代比在最后一个维度上进行迭代更有效:

data = numpy.random.randint(0, 10, size=(10000, 10000))
%timeit colwise_func(data)  # 1.08 s ± 35.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit rowwise_func(data)  # 2.31 s ± 65.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

答案 1 :(得分:0)

您可以使用数据的二进制数组。定义阈值后,请使用class Program { ConcurrentDictionary<double, Store> _StoreQueue = new ConcurrentDictionary<double, Store>(); static void Main(string[] args) { var T = 17d; // try to add if not exit the store with 17 _StoreQueue.GetOrAdd(T, new Store(T)); } public class Store { public double TimeStamp { get; set; } public Store(double timeStamp) { TimeStamp = timeStamp; } } } 将其二值化:

np.where

data = np.array([-3, 4, -2, -2, 6]) binarized = np.where(data>0, 1, 0) # array([0, 1, 0, 0, 1]) 函数返回一个与np.where相同大小的数组,其中任何高于阈值(此处等于0)的值都将设置为1,所有其他值都将设置为0。

然后简单地将其累加总和与其自身相乘。它将对所有值求和,并在没有有效和的地方将其设置为零。

data

对于二维数组,请使用类似的方法,但要提供要求和的轴。在您的情况下,您希望将其沿行放置,因此将其设置为np.cumsum(binarized)*binarized # array([0, 1, 0, 0, 2])

axis=1

您的功能只能是:

data = np.array([[-3, 4, -2, -2, 6],[1, -2, -3, 7, 1]])
binarized = np.where(data>0, 1, 0)
np.cumsum(binarized, axis=1)*binarized
# array([[0, 1, 0, 0, 2],
#        [1, 0, 0, 2, 3]])

参数def func(data, t=0, ax=1): b = np.where(data>t, 1, 0) return np.cumsum(b, axis=ax)*b 用于设置阈值,而参数t是用于求和的轴。给出ax将对数组的所有值求和。