HOWTO · Python
Implementar filtro de paso bajo en Python
Aprende a filtrar datos muestreados en Python con un filtro Butterworth de SciPy, una media móvil o un suavizado gaussiano, y comprende la frecuencia de corte y los límites de muestreo.
En esta página
Un filtro paso bajo deja pasar las componentes de menor frecuencia y atenúa las de mayor frecuencia; no necesariamente elimina todas las componentes por encima de la frecuencia de corte. Para datos muestreados, elige la frecuencia de corte en las mismas unidades que la frecuencia de muestreo. Esta guía presenta tres formas de filtrar o suavizar una señal unidimensional con NumPy y SciPy.
Los ejemplos siguientes son independientes, pero no se ejecutan aquí ni se muestran resultados de ellos. Instala NumPy, SciPy y Matplotlib en tu entorno de Python antes de ejecutarlos.
Usar un filtro Butterworth de SciPy con una frecuencia de corte definida
Un diseño Butterworth tiene una banda de paso máximamente plana. Fija la frecuencia de corte por debajo de la frecuencia de Nyquist, que equivale a la mitad de la frecuencia de muestreo. En el ejemplo, fs es de 500 muestras por segundo y la frecuencia de corte es de 100 Hz. Al pasar fs a scipy.signal.butter, puedes expresar la frecuencia de corte en esas mismas unidades. El orden controla la pendiente de la transición: un orden mayor produce una caída más pronunciada, pero también aumenta la sensibilidad a los transitorios y al comportamiento numérico.
Este ejemplo usa secciones de segundo orden y sosfiltfilt para filtrar en sentido directo e inverso. Así se evita el retardo de fase en el análisis fuera de línea, pero se necesitan datos de ambas direcciones y el resultado puede verse afectado en los extremos de una señal finita. Para datos en flujo o en tiempo real, usa un filtro causal como sosfilt y ten en cuenta su retardo de fase y el transitorio inicial.
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import butter, sosfiltfilt
fs = 500.0
cutoff = 100.0
order = 4
time = np.arange(500) / fs
signal = np.sin(2 * np.pi * 10 * time) + 0.5 * np.sin(2 * np.pi * 180 * time)
sections = butter(order, cutoff, btype="lowpass", fs=fs, output="sos")
filtered = sosfiltfilt(sections, signal)
plt.plot(time, signal, label="input")
plt.plot(time, filtered, label="filtered")
plt.xlabel("Time (seconds)")
plt.ylabel("Amplitude")
plt.legend()
plt.tight_layout()
plt.show()
Ajusta cutoff y order según la señal y las frecuencias que quieras conservar. sosfiltfilt está pensado para datos procesados fuera de línea; su resultado no es intercambiable con el de un filtro causal en tiempo real.
Aplicar un filtro paso bajo de media móvil
Una media móvil sustituye cada punto por la media de una ventana de tamaño fijo. Es un método sencillo para suavizar, pero no es un diseño Butterworth con una respuesta de frecuencia de corte especificada. Con el modo de convolución valid de NumPy, el resultado solo incluye ventanas completas, por lo que tiene window_size - 1 muestras menos que la entrada. Al representarlo, alinea los valores de tiempo en consecuencia.
import matplotlib.pyplot as plt
import numpy as np
fs = 100.0
window_size = 5
time = np.arange(100) / fs
signal = np.sin(2 * np.pi * 3 * time) + 0.2 * np.sin(2 * np.pi * 25 * time)
weights = np.ones(window_size) / window_size
smoothed = np.convolve(signal, weights, mode="valid")
smoothed_time = time[window_size - 1:]
plt.plot(time, signal, label="input")
plt.plot(smoothed_time, smoothed, label="moving average")
plt.xlabel("Time (seconds)")
plt.ylabel("Amplitude")
plt.legend()
plt.tight_layout()
plt.show()
Elige un tamaño de ventana positivo que no supere la longitud de la señal. Al aumentar la ventana, se promedian más muestras y el suavizado es más intenso, pero también se ensanchan los cambios y se desplaza la alineación del resultado. Si usas una alineación centrada, ten en cuenta el retardo de la ventana al interpretar los valores de tiempo.
Usar un filtro gaussiano para suavizar datos muestreados
Un filtro gaussiano unidimensional asigna pesos a las muestras cercanas mediante un núcleo con forma gaussiana. En scipy.ndimage.gaussian_filter1d, sigma se mide en muestras, no en segundos ni en hercios. Si hace falta, convierte la escala temporal deseada a muestras usando la frecuencia de muestreo. El suavizado gaussiano sirve para lograr un suavizado general, pero no crea una frecuencia de corte nítida y especificada.
import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage import gaussian_filter1d
fs = 100.0
sigma_seconds = 0.04
time = np.arange(100) / fs
signal = np.sin(2 * np.pi * 3 * time) + 0.2 * np.sin(2 * np.pi * 25 * time)
smoothed = gaussian_filter1d(signal, sigma=sigma_seconds * fs)
plt.plot(time, signal, label="input")
plt.plot(time, smoothed, label="Gaussian smoothed")
plt.xlabel("Time (seconds)")
plt.ylabel("Amplitude")
plt.legend()
plt.tight_layout()
plt.show()
El ejemplo convierte una escala de suavizado de 0.04 segundos en cuatro muestras. El comportamiento predeterminado trata los extremos reflejando la señal; elige otro mode si tus datos requieren un modelo distinto para los extremos y presta atención al interpretarlos.
Elegir un filtro y entender sus límites
Usa un diseño Butterworth cuando necesites una respuesta de frecuencia definida y conozcas la frecuencia de muestreo. Usa una media móvil para un suavizador sencillo basado en ventanas, o un suavizado gaussiano cuando convenga asignar pesos suaves a las muestras cercanas. Estos métodos tienen respuestas, retardos y comportamientos en los extremos distintos; compara el resultado con los datos originales y comprueba que sigan visibles las características importantes para tu tarea.
En datos muestreados, la frecuencia de Nyquist equivale a la mitad de la frecuencia de muestreo. La frecuencia de corte de un filtro paso bajo debe quedar por debajo de Nyquist, y la frecuencia de muestreo debe ser suficiente para representar las frecuencias de interés. Ningún filtro puede recuperar información que no se capturó durante el muestreo. El filtrado directo e inverso fuera de línea puede reducir el desfase, mientras que el filtrado causal sirve para procesar datos en flujo, pero introduce retardo y un comportamiento transitorio inicial. En registros finitos, el relleno y las condiciones iniciales también pueden influir más en los resultados cerca de los extremos.
Preguntas frecuentes
¿Qué hace un filtro paso bajo?
Deja pasar las componentes de menor frecuencia y atenúa las de mayor frecuencia según su respuesta. La frecuencia de corte marca una transición en esa respuesta; no significa que todas las frecuencias superiores desaparezcan por completo.
¿Cuándo conviene usar un filtro paso bajo?
Úsalo cuando la variación de mayor frecuencia sea ruido para tu tarea y conozcas la frecuencia de muestreo y la frecuencia de corte. Comprueba que el suavizado no elimine cambios rápidos importantes de la señal.
¿En qué se diferencia un filtro Butterworth de una media móvil?
Un filtro Butterworth se diseña a partir de una frecuencia de corte, una frecuencia de muestreo y un orden. Una media móvil usa un número fijo de muestras por ventana y tiene una respuesta de frecuencia distinta; la longitud de su ventana no sustituye directamente a la frecuencia de corte de un Butterworth.
¿Puedo usar estos filtros con datos en tiempo real?
Un filtro causal puede procesar las muestras a medida que llegan, pero hay que tener en cuenta su retardo de fase y el transitorio inicial. El método de filtrado directo e inverso del ejemplo Butterworth necesita el registro completo y está pensado para el procesamiento fuera de línea. Una media móvil puede actualizarse conforme llegan muestras si controlas su ventana y su alineación.
¿Qué bibliotecas de Python puedo usar?
NumPy proporciona arreglos y funciones de convolución, mientras que SciPy incluye funciones para diseñar filtros Butterworth y aplicar suavizado gaussiano. Matplotlib permite representar las señales de entrada y filtradas para inspeccionarlas.