I have a Timeseries (s) which need to be processed recursively to get a timeseries result (res). Here is my sample code:
res=s.copy()*0
res[1]=k # k is a constant
for i in range(2,len(s)):
res[i]=c1*(s[i]+s[i-1])/2 +c2*res[i-1]+c3*res[i-2]
where c1,c2,c3 are constants. It works properly but I'd like to use vectorization and I tried with:
res[2:]=c1*(s[2:]+s[1:-1])/2+c2*res[1:-1]+c3*res[0:-2]
but I get "ValueError: operands could not be broadcast together with shapes (1016) (1018) "
if I try with
res=c1*(s[2:]+s[1:-1])/2+c2*res[1:-1]+c3*res[0:-2]
doesn't give any error, but I don't get a correct result, because res[0] and res[1] have to be initialized before the calculation will take place.
Is there a way to process it with vectorization?
Any help will be appreciated, thanks!
This expression
says that
res
is the output of a linear filter (or ARMA process) with inputs
. Several libraries have functions for computing this. Here's how you can use the scipy functionscipy.signal.lfilter
.From inspection of the recurrence relation, we get the coefficients of the numerator (
b
) and denominator (a
) of the filter's transfer function:We'll also need an appropriate initial condition for
lfilter
to handleres[:2] == [0, k]
. For this, we usescipy.signal.lfiltic
:In the simplest case, one would call
lfilter
like this:With an initial condition
zi
, we use:However, to exactly match the calculation provided in the question, we need the output
y
to start with[0, k]
. So we'll allocate an arrayy
, initialize the first two elements with[0, k]
, and assign the output oflfilter
toy[2:]
:Here's a complete script with the original loop and with
lfilter
:The output is:
lfilter
accepts anaxis
argument, so you can filter an array of signals with a single call.lfiltic
does not have anaxis
argument, so setting up the initial conditions requires a loop. The following script shows an example.Plot: