How to Implement IIR Filter in Python: Simple Guide
To implement an
IIR filter in Python, use the scipy.signal library's iirfilter or butter functions to design filter coefficients, then apply the filter with lfilter. This approach lets you create filters like Butterworth easily and apply them to your data arrays.Syntax
The main steps to implement an IIR filter in Python are:
scipy.signal.iirfilter(N, Wn, btype, ftype): Designs the filter and returns coefficients.scipy.signal.lfilter(b, a, data): Applies the filter to your data using coefficients.
Here, N is the filter order, Wn is the cutoff frequency (normalized), btype is the filter type (e.g., 'low', 'high'), and ftype is the filter design type (e.g., 'butter').
python
from scipy.signal import iirfilter, lfilter # Design IIR filter coefficients b, a = iirfilter(N=4, Wn=0.2, btype='low', ftype='butter') # Apply filter to data filtered_data = lfilter(b, a, data)
Example
This example creates a 4th order lowpass Butterworth IIR filter with cutoff frequency 0.2 (normalized), then filters a noisy sine wave signal.
python
import numpy as np import matplotlib.pyplot as plt from scipy.signal import iirfilter, lfilter # Create sample data: noisy sine wave fs = 100 # Sampling frequency T = 2 # seconds t = np.linspace(0, T, int(T*fs), endpoint=False) signal = np.sin(2 * np.pi * 5 * t) + 0.5 * np.random.randn(len(t)) # Design 4th order lowpass Butterworth filter with cutoff 0.2 (Nyquist normalized) b, a = iirfilter(N=4, Wn=0.2, btype='low', ftype='butter') # Filter the signal filtered_signal = lfilter(b, a, signal) # Plot original and filtered signals plt.figure(figsize=(10, 4)) plt.plot(t, signal, label='Noisy Signal') plt.plot(t, filtered_signal, label='Filtered Signal', linewidth=2) plt.xlabel('Time [seconds]') plt.ylabel('Amplitude') plt.legend() plt.title('IIR Lowpass Filter Example') plt.tight_layout() plt.show()
Output
A plot window showing two lines: a noisy sine wave and a smoother filtered sine wave.
Common Pitfalls
- Not normalizing cutoff frequency: The cutoff
Wnmust be between 0 and 1, where 1 corresponds to Nyquist frequency (half the sampling rate). - Using wrong filter order: Too high order can cause instability; too low order may not filter well.
- Applying filter incorrectly: Use
lfilterwith the correct coefficientsbanda. - Ignoring phase distortion: IIR filters can distort phase; use
filtfiltfor zero-phase filtering if needed.
python
from scipy.signal import iirfilter, lfilter, filtfilt import numpy as np # Wrong: cutoff frequency not normalized (e.g., 20 instead of 0.2) try: b, a = iirfilter(N=4, Wn=20, btype='low', ftype='butter') except ValueError as e: print(f'Error: {e}') # Right: normalized cutoff frequency b, a = iirfilter(N=4, Wn=0.2, btype='low', ftype='butter') # Sample data data = np.sin(np.linspace(0, 10, 100)) # Apply filter (causes phase shift) filtered = lfilter(b, a, data) # Apply zero-phase filter to avoid phase distortion filtered_zero_phase = filtfilt(b, a, data) print('Filtered with lfilter:', filtered[:5]) print('Filtered with filtfilt:', filtered_zero_phase[:5])
Output
Error: Wn must be between 0 and 1
Filtered with lfilter: [0. 0.00123922 0.00615127 0.01402743 0.02416904]
Filtered with filtfilt: [0.00000000e+00 1.23922244e-03 6.15126959e-03 1.40274291e-02 2.41690357e-02]
Quick Reference
Remember these key points when implementing IIR filters in Python:
iirfilterdesigns filter coefficients.lfilterapplies the filter to data.- Cutoff frequency
Wnmust be normalized (0 to 1). - Use
filtfiltfor zero-phase filtering to avoid phase shifts. - Choose filter order carefully to balance performance and stability.
Key Takeaways
Use scipy.signal.iirfilter to design IIR filter coefficients with normalized cutoff frequency.
Apply the filter to data using scipy.signal.lfilter or filtfilt for zero-phase filtering.
Always normalize cutoff frequency between 0 and 1 relative to Nyquist frequency.
Beware of phase distortion with lfilter; use filtfilt if phase preservation is important.
Choose filter order carefully to avoid instability or poor filtering.