11

我有一组值a = (2,3,0,0,4,3)

y=0
for x in a:
  y = (y+x)*.95

cumsum在添加下一个值之前,有什么方法可以使用numpy并将 .95 衰减应用于每一行?

4

4 回答 4

8

您需要一个简单的IIR Filter。Scipy 的lfilter()就是为此而设计的:

import numpy as np
from scipy.signal import lfilter

data = np.array([2, 3, 0, 0, 4, 3], dtype=float)  # lfilter wants floats

# Conventional approach:
result_conv = []
last_value = 0
for elmt in data:
    last_value = (last_value + elmt)*.95
    result_conv.append(last_value)

# IIR Filter:
result_IIR = lfilter([.95], [1, -.95], data)

if np.allclose(result_IIR, result_conv, 1e-12):
    print("Values are equal.")
于 2015-03-07T13:19:26.213 回答
5

如果您只处理一维数组,那么缺少 scipy 便利或为 numpy 编写自定义 reduce ufunc,那么在 Python 3.3+ 中,您可以使用itertools.accumulate,例如:

from itertools import accumulate

a = (2,3,0,0,4,3)
y = list(accumulate(a, lambda x,y: (x+y)*0.95))
# [2, 4.75, 4.5125, 4.286875, 7.87253125, 10.3289046875]
于 2015-03-07T13:38:52.373 回答
3

Numba 为函数提供了一种简单的方法vectorize,创建了一个通用函数(因此提供了ufunc.accumulate):

import numpy
from numba import vectorize, float64

@vectorize([float64(float64, float64)])
def f(x, y):
    return 0.95 * (x + y)

>>> a = numpy.array([2, 3, 0, 0, 4, 3])
>>> f.accumulate(a)
array([  2.        ,   4.75      ,   4.5125    ,   4.286875  ,
         7.87253125,  10.32890469])
于 2017-10-21T07:02:42.367 回答
1

我不认为这可以在 NumPy 中轻松完成,而无需使用循环。

一种基于数组的想法是计算矩阵 M_ij = .95**i * a[Nj](其中 N 是 a 中的元素数)。您正在寻找的数字是通过对角求和条目(使用 ij 常数)找到的。因此,您可以使用多个numpy.diagonal(…).sum().

您概述的旧算法更清晰并且可能已经相当快(否则您可以使用 Cython)。

通过 NumPy 做你想做的事,没有一个循环对我来说听起来像是魔法。向任何能做到这一点的人致敬。

于 2015-03-07T13:13:24.863 回答