您的位置:

多面解析np.cumsum

一、常规定义

1、np.cumsum可以对输入数组的元素进行累加操作,返回一个由累加值组成的新数组。

2、沿着指定轴的元素进行 sum 操作。对于类型为float的数组,数值累加可能会导致精度损失。对于保持精度的求和,使用cumsum。

3、cumsum(a, dtype=float)的累加器保持所需的精度。类型由a决定。a的类型不能改变。如果a的类型为int,那么累加器的类型会是np.int32或np.int64(取决于平台),而对于其他类型,它们会如上述。


import numpy as np
a = np.array([1,2,3])
print(np.cumsum(a)) #[1, 3, 6]

b = np.array([(1,2,3),(4,5,6)])
print(np.cumsum(b, axis=0)) #[[1,2,3], [5,7,9]])
print(np.cumsum(b, axis=1)) #[[1,3,6], [4,9,15]]

二、利用np.cumsum做滑动平均

1、在滤波器设计中,将其作为模拟器,以近似系统函数或信号的衰减速度的方法使用cumsum。

2、累加之后计算平均,这是一种用于计算数据序列的平均值的技术。例如,在时间序列数据中可以将np.cumsum与np.arange结合使用,以计算数据的滑动平均值。


def moving_average(a, n=3) :
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n

a = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
print(moving_average(a, n=3)) #[ 2.  3.  4.]

三、用np.cumsum实现分组且分组后每组内部求和

1、可以用np.cumsum实现下面的操作:对输入数组划分为几段,每段内部元素求和后输出。

2、我们可以通过先计算原始数组的累计总和,并将每个段开头偏移一定数量的元素,获得每个分段的求和结果。


def segment_sum(a, L):
    # 求得每个分块的头和尾位置
    limits = list(range(0, len(a), L)) + [len(a)]
    # 依次对相邻分块累加求和,np.diff得到每个分块累加和
    sums = [np.cumsum(a[limits[i]:limits[i+1]]) for i in range(len(limits) - 1)]
    return np.concatenate(sums)

a = np.array([1,2,3,4,5,6,7,8,9])
print(segment_sum(a, 3)) #[6, 15, 24, 17]

四、利用np.cumsum实现局部最小值/最大值的检测

1、通过计算差异值并使用布尔掩码,可以轻松地从数据点中识别出局部最小值或局部最大值。

2、该方法基于以下性质:如果当前值小于其相邻值,则当前值在局部最小值上,相反,如果当前值大于其相邻值,则当前值在局部最大值上。


def local_minmax(a):
    # 计算如果是局部最小值/最大值则差异值的正负符号
    diff = np.diff(a)
    # 获得布尔掩码,其中差异为正则表示其在局部最大值上,反之在局部最小值上
    mask = np.concatenate(([False], diff[:-1] * diff[1:] < 0, [False]))
    # 返回局部最小值和局部最大值的点 Vales
    if not mask.any():
        return np.array([], dtype=int), np.array([], dtype=int)
    else:
        extrema = np.where(mask)[0]
        return extrema, a[extrema]

a = np.array([1,3,2,4,3,5,4,6,7,8,6,3,4,2])
minima_idx, minima_val = local_minmax(a)
print(minima_idx, minima_val) # [1 , 2, 3, 4, 6, 11 , 13] [ 3 2 3 4 4 3 2]