# Can I use IIR or FIR to get a sliding mean?

My output signal shall be computed by (meta code):

o = 0  # or some arbitrary initial value
for i in input:
o = (o * 99 + i) / 100
print o


I call this a "sliding mean", but maybe another term is established for this. (If so, mentioning this could help me researching this better ;-)

Is there a way to achieve this using the a / b coefficient arrays of IIRs or FIRs? What would they look like?

I'm aiming at a solution in Python / scipy.signal.

Or is there another established way to achieve this which I can find in such libraries like numpy, scipy, pandas, etc.?

• Can I please ask you to describe in words what your pseudo-code is describing (?). I get a feeling that there is a mismatch between what you are trying to do and what is described by that snippet. Also, yes, there possibly is a DSP operation that does what (I think) you are after. – A_A Jan 31 '18 at 9:10
• Each output value is 99% the former output value and 1% the current input value. See @tendero 's answer which was exactly what I was looking for. My playing around with the a and b and my understanding of their effects just wasn't thorough enough to find the correct values. a=[1;0.99] and b=[0.01] was what I was looking for. – Alfe Jan 31 '18 at 9:20
• The exact same thing (basically, an IIR filter) emerges also as a particular steady state solution to a Kalman Filter. I tried to find the original reference but I cannot locate the book right now. You might want to have a look at page 17, "Mixture Applications", in this reference instead. There is an equivalence between EWMA and that particular Kalman solution which is what I had in mind. For some reason, although older, the answers were not visible when I accessed the Q. – A_A Jan 31 '18 at 11:51

It corresponds to an exponentially weighted moving average (EWMA) filter with parameter $\alpha = 0.01$.

The difference equation can be expressed as:

$$y(n)-(1-\alpha)y(n-1)=\alpha x(n)$$ $$y(n)-0.99y(n-1)=0.01 x(n)$$

Thus it's an IIR filter. You can easily get the coefficients from the difference equation.

$$Y(z)-0.99z^{-1}Y(z)=0.01X(z)$$ $$\frac{Y(z)}{X(z)}=\frac{0.01}{1-0.99z^{-1}}$$

Therefore, a = [1 ; -0.99] and b = 0.01.

It is also called exponential smoothing due to the fact that contributions from past values decay at an exponential rate.

When it is applied to sinusoids, the math is interesting because sinusoidal are also exponential. The filter introduces a frequency dependent phase lag when applied to a pure tone.

A clever trick is to also perform an exponential smoothing of your data in the reverse direction and to average the results. The forward lag cancels the backward lag and you get a smoothed version of your original signal with all phases intact. The amplitude of a pure tone is attenuated by a frequency dependent formula. Therefore, you can apply analysis techniques, such as using a DFT, and get better results since the smoothing acts as a noise reduction technique.

I cover the math for this in a blog article called "Exponential Smoothing with a Wrinkle".

Hope this helps.

Ced

• Interesting article, thank you for the pointer! – Alfe Jan 30 '18 at 23:07

I think it is called an exponential averager. It is also an order-1 IIR.

Your coefficients are a0 = 1, a1 = -0.99, b0 = 0.01, b1 =0

Since you've called it "sliding mean", I presume that's the functionality you actually want – and yes, that's actually a FIR filter, we'd call it "moving average".

A naive implementation of that would be [ 1.0 / L ] * L, so, an L long moving average implemented as FIR taps:

 fir_taps = [ 1.0 / L ] * L
signal_out = numpy.convolve(signal_in, fir_taps)


For small L, this is a very sufficient method; for lengthier averages, a version where you only add the newest and subtract the oldest value might perform better.

Notice that both your IIR form (which we call EWMA, or single-pole IIR integrator) are low-pass filters. If you actually need a behaviour that suppresses high-speed signal components, then an averaging filter is not the best you can do!

• That would have been a fixed window width (which is not what I wanted). Thanks anyway. pandas has a Series(arr).rolling() functionality which covers this quite efficiently, btw., also with a wide variance of window functions (hamming, etc.). – Alfe Jan 30 '18 at 23:04