lfilter() implements a general linear filter defined by two coefficient arrays: b, the numerator, feedforward coefficients, and a, the denominator, feedback coefficients — setting a to just [1] produces a simple FIR, finite impulse response, filter that only depends on current and past input values, while a genuinely multi-element a produces an IIR, infinite impulse response, filter, which also feeds back its own past output values, letting a short set of coefficients implement effects that would otherwise require a very long FIR filter. It's the general building block underlying many specific filtering operations, like simple moving averages, exponential smoothing, and more sophisticated frequency-selective filters designed with functions like signal.butter().
1Understanding signal.lfilter()
lfilter() implements a general linear filter defined by two coefficient arrays: b, the numerator, feedforward coefficients, and a, the denominator, feedback coefficients — setting a to just [1] produces a simple FIR, finite impulse response, filter that only depends on current and past input values, while a genuinely multi-element a produces an IIR, infinite impulse response, filter, which also feeds back its own past output values, letting a short set of coefficients implement effects that would otherwise require a very long FIR filter. It's the general building block underlying many specific filtering operations, like simple moving averages, exponential smoothing, and more sophisticated frequency-selective filters designed with functions like signal.butter().
A simple moving average filter can be implemented directly with lfilter() by setting b to an array of equal weights that sum to 1, and a to just [1] — this is a quick way to smooth noisy data without needing a specialized smoothing function.
from scipy import signal
import numpy as np
x = np.array([1, 2, 3, 4, 5], dtype=float)
b = [1/3, 1/3, 1/3]
a = [1]
filtered = signal.lfilter(b, a, x)
print(np.round(filtered, 2))2Practical Example
Here is a real-world application of signal.lfilter() showing how it is used in production SciPy code.
from scipy import signal
import numpy as np
x = np.array([1, 1, 1, 1, 1], dtype=float)
b = [1]
a = [1, -0.5]
filtered = signal.lfilter(b, a, x)
print(np.round(filtered, 3))3Best Practices
Follow these guidelines when working with signal.lfilter():
1. Use lfilter() directly for straightforward FIR filters, simple moving averages, basic differencing, by setting a to [1] and choosing b's coefficients appropriately
2. Design more sophisticated frequency-selective filters, low-pass, high-pass, etc., with a dedicated function like signal.butter(), then apply the resulting b/a coefficients with lfilter(), rather than hand-deriving filter coefficients yourself
3. Use signal.filtfilt() instead of lfilter() when you need zero-phase filtering, no time delay/shift introduced by the filter, since lfilter() alone introduces a phase shift
Tip: A simple moving average filter can be implemented directly with lfilter() by setting b to an array of equal weights that sum to 1, and a to just [1] — this is a quick way to smooth noisy data without needing a specialized smoothing function.
from scipy import signal
import numpy as np
x = np.array([1, 2, 3, 4, 5], dtype=float)
b = [1/3, 1/3, 1/3]
a = [1]
filtered = signal.lfilter(b, a, x)
print(np.round(filtered, 2))