How to Implement Filter Using SciPy in Signal Processing
To implement a filter using
scipy, use the scipy.signal module which provides functions like butter to design filters and lfilter to apply them. First, design the filter coefficients, then apply the filter to your data with lfilter.Syntax
The basic steps to implement a filter using scipy.signal are:
b, a = scipy.signal.butter(order, cutoff, btype='low', fs=sample_rate): Designs a Butterworth filter and returns filter coefficientsbanda.filtered_signal = scipy.signal.lfilter(b, a, data): Applies the filter to your data array.
Explanation:
order: The filter order (controls sharpness).cutoff: Cutoff frequency (or frequencies for band filters).btype: Filter type - 'low', 'high', 'bandpass', or 'bandstop'.fs: Sampling frequency of your data.b, a: Numerator and denominator coefficients of the filter.data: The input signal to filter.
python
from scipy.signal import butter, lfilter def butter_filter(data, cutoff, fs, order=5, btype='low'): b, a = butter(order, cutoff, btype=btype, fs=fs) y = lfilter(b, a, data) return y
Example
This example creates a noisy signal and applies a low-pass Butterworth filter to remove high-frequency noise.
python
import numpy as np import matplotlib.pyplot as plt from scipy.signal import butter, lfilter # Create a sample signal: 5 Hz sine wave + noise fs = 100.0 # Sampling frequency T = 2.0 # seconds n = int(T * fs) # total samples t = np.linspace(0, T, n, endpoint=False) signal = np.sin(2 * np.pi * 5 * t) + 0.5 * np.random.randn(n) # Design a low-pass filter with cutoff at 10 Hz order = 4 cutoff = 10 b, a = butter(order, cutoff, btype='low', fs=fs) filtered_signal = lfilter(b, a, signal) # Plot original and filtered signals plt.figure(figsize=(10, 6)) 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('Low-pass Butterworth Filter using scipy.signal') plt.show()
Output
A plot window showing two lines: a noisy sine wave and a smoother filtered sine wave.
Common Pitfalls
- Not specifying the sampling frequency
fsinbuttercan cause incorrect cutoff frequency interpretation. - Using
lfilterintroduces phase delay; usefiltfiltfor zero-phase filtering if needed. - Choosing too high filter order can cause instability or ringing effects.
- For bandpass or bandstop filters, cutoff must be a list or tuple of two frequencies.
python
from scipy.signal import butter, lfilter, filtfilt # Wrong: missing fs parameter, cutoff interpreted incorrectly b, a = butter(4, 0.1, btype='low') # 0.1 means 0.1 * Nyquist frequency # Right: specify fs to use Hz directly fs = 100 b, a = butter(4, 10, btype='low', fs=fs) # Wrong: using lfilter causes phase delay filtered = lfilter(b, a, signal) # Right: use filtfilt for zero-phase filtering filtered_zero_phase = filtfilt(b, a, signal)
Quick Reference
Summary tips for filtering with scipy.signal:
- Use
butterto design Butterworth filters. - Always specify
fsto define cutoff in Hz. - Apply filter with
lfilter(causes delay) orfiltfilt(zero-phase). - Choose filter order carefully to balance sharpness and stability.
- For band filters, provide cutoff as a tuple (low, high).
Key Takeaways
Use scipy.signal.butter to design filter coefficients with specified order and cutoff.
Apply filters with lfilter for causal filtering or filtfilt for zero-phase filtering.
Always specify the sampling frequency fs to correctly interpret cutoff frequencies.
Avoid too high filter order to prevent instability and ringing.
For bandpass or bandstop filters, provide cutoff as a tuple of frequencies.