python - 如何将 Numpy 中的累积和应用于条件为前一个值的切片?

标签 python arrays numpy

我有一个向量,其信号值为 1-1。我想要第二个向量,它计算具有相同值的连续信号的累积和,并在每次信号变化时重新启动累积和。这是一个例子:

signal  = [1  1  1 -1 -1 -1 -1]

cum_sum = [1  2  3 -1 -2 -3 -4]

我有大量数据需要计算,并且希望尽可能高效地进行计算。 我的代码现在可以完成这项工作,但需要时间并且没有利用 numpy 效率:

import numpy as np

# Signal values to be analyzed
signal = np.array([1,1,1,-1,-1,-1,-1], dtype=int)

# Vector with previous value of signal
signal_prev = signal[:-1]
signal_prev = np.pad(signal_prev,(1,0), mode='constant', constant_values=(0))

#Array with signal values in first column and previous values in second column 
arr = np.array([signal,signal_prev], dtype=int)
arr = np.transpose(arr)

print(arr)
""" Array with signal values and previous values
[[ 1  0]
 [ 1  1]
 [ 1  1]
 [-1  1]
 [-1 -1]
 [-1 -1]
 [-1 -1]]
"""

#create an empty array to append cumulative sum
signal_sum = np.array([], dtype=int)

# compute the cumulative sum iterating row by row
for x in arr:
    if np.sign(x[0]*x[1]) > 0:
        signal_sum = np.append(signal_sum, signal_sum[-1] + x[1])
    else:
        signal_sum= np.append(signal_sum, x[0])

arr_sum = np.array([signal, signal_sum])
arr_sum = np.transpose(arr_sum)
print(arr_sum)
""" Array with signal values and cumulative sum restarted with signal change
[[ 1  1]
 [ 1  2]
 [ 1  3]
 [-1 -1]
 [-1 -2]
 [-1 -3]
 [-1 -4]]
"""

我相信使用 numpy 函数或 lambda 函数可以更有效地完成此计算。我不是程序员,而且我是 Python 新手。我想知道这是否可以做得更快。

最佳答案

对于快速、完全矢量化的方式(无循环),您可以使用常规的np.cumsum(),但在数组的副本上进行减去每组开始时的前一组总和:

def group_cumsum(s):
    # make a copy and ensure np.array (in case list was given)
    s = np.array(s).copy()
    idx = np.nonzero(np.diff(s))[0]  # last of each group
    off = np.diff(np.concatenate(([0], np.cumsum(s)[idx])))
    s[idx + 1] -= off
    return np.cumsum(s)

示例:

print(group_cumsum([1, 1, 1, -1, -1, -1, -1]))
# [ 1  2  3 -1 -2 -3 -4]

print(group_cumsum([1]*3 + [-1]*2 + [1]*4 + [-1]*5))
# [ 1  2  3 -1 -2  1  2  3  4 -1 -2 -3 -4 -5]

对于大型数组来说,节省了大量的时间:

  1. Python 代码中没有循环,所有操作均已向量化,并且
  2. 对于大小为 n 的数组中的 k 个组,其复杂度为 O(n + k)(与 O(n * k))。

试试这个:

s = np.random.choice([1, -1], size=(int(1e6)))

%%timeit
group_cumsum(s)

19.1 ms ± 137 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

关于python - 如何将 Numpy 中的累积和应用于条件为前一个值的切片?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65264898/

相关文章:

python - 列操作 R

python - 如何评估具有预测长度的列表? (`tensorflow.nn.top_k` 以及来自另一个模型的 `k` 数组)

c - C 的 std::vector 替代品

c++ - 是否可以在没有循环的情况下将数组元素与硬编码的初始值设定项列表进行比较?

python - 规范化列 : sum to 1

python - 预期为二维数组,得到一维数组

python - 在 numpy 数组中从末尾切片可变距离的更多 Pythonic 方法

python-无法使用 Homebrew 安装的模块?

Python 日期比较

arrays - 将数组作为 x-www-form-urlencoded 的一部分发送