FILTFILT
The filtfilt function applies a linear digital filter twice, once forward and once backwards. The combined filter has zero phase distortion and a filter order twice that of the original.
This technique is primarily used when it is important to preserve the timing of features in the signal (i.e., zero phase shift), at the cost of being an offline/non-real-time process.
Excel Usage
=FILTFILT(x, b, a, axis, padtype, padlen, filtfilt_method, irlen)
x(list[list], required): The input array of data to be filtered.b(list[list], required): The numerator coefficient vector of the filter (1D array in Excel).a(list[list], required): The denominator coefficient vector of the filter (1D array in Excel).axis(int, optional, default: -1): The axis along which the filter is applied.padtype(str, optional, default: “odd”): Extension mode for padding at edges.padlen(int, optional, default: null): Number of elements to extend x by at both ends.filtfilt_method(str, optional, default: “pad”): Method for handling edges.irlen(int, optional, default: null): Impulse response length for Gustafsson’s method.
Returns (list[list]): The filtered signal as a 2D array.
Example 1: Zero-phase filtering
Inputs:
| x | b | a | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 4 | 3 | 2 | 1 | 0.02008337 | 0.04016673 | 0.02008337 | 1 | -1.56101808 | 0.64135154 |
Excel formula:
=FILTFILT({1,2,3,4,5,4,3,2,1}, {0.02008337,0.04016673,0.02008337}, {1,-1.56101808,0.64135154})
Expected output:
| Result | ||||||||
|---|---|---|---|---|---|---|---|---|
| 1.04833 | 1.45384 | 1.79308 | 2.02166 | 2.1079 | 2.0395 | 1.82648 | 1.49805 | 1.09582 |
Example 2: Gustafsson’s method
Inputs:
| x | b | a | filtfilt_method | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 4 | 3 | 2 | 1 | 0.02008337 | 0.04016673 | 0.02008337 | 1 | -1.56101808 | 0.64135154 | gust |
Excel formula:
=FILTFILT({1,2,3,4,5,4,3,2,1}, {0.02008337,0.04016673,0.02008337}, {1,-1.56101808,0.64135154}, "gust")
Expected output:
| Result | ||||||||
|---|---|---|---|---|---|---|---|---|
| 2.85538 | 2.9054 | 2.95971 | 3.00267 | 3.01908 | 3.00267 | 2.95971 | 2.9054 | 2.85538 |
Python Code
Show Code
import numpy as np
from scipy.signal import filtfilt as scipy_filtfilt
def filtfilt(x, b, a, axis=-1, padtype='odd', padlen=None, filtfilt_method='pad', irlen=None):
"""
Apply a digital filter forward and backward to a signal for zero phase distortion.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.filtfilt.html
This example function is provided as-is without any representation of accuracy.
Args:
x (list[list]): The input array of data to be filtered.
b (list[list]): The numerator coefficient vector of the filter (1D array in Excel).
a (list[list]): The denominator coefficient vector of the filter (1D array in Excel).
axis (int, optional): The axis along which the filter is applied. Default is -1.
padtype (str, optional): Extension mode for padding at edges. Valid options: Odd, Even, Constant. Default is 'odd'.
padlen (int, optional): Number of elements to extend x by at both ends. Default is None.
filtfilt_method (str, optional): Method for handling edges. Valid options: Pad, Gustafsson. Default is 'pad'.
irlen (int, optional): Impulse response length for Gustafsson's method. Default is None.
Returns:
list[list]: The filtered signal as a 2D array.
"""
try:
def to_1d(v):
if isinstance(v, list):
return np.array([float(x) for row in v for x in row])
return np.array([float(v)])
def to2d(x):
return [[x]] if not isinstance(x, list) else x
x_arr = np.array(to2d(x))
b_arr = to_1d(b)
a_arr = to_1d(a)
# SciPy's filtfilt requires len(x) > padlen. If no padlen is provided, it
# defaults to 3*max(len(a), len(b)), which can be too large for short inputs.
# In that case, shrink padlen to len(x)-1 so the call succeeds.
padlen_arg = int(padlen) if padlen is not None else None
if padlen is None:
axis_int = int(axis)
if axis_int < 0:
axis_int = x_arr.ndim + axis_int
x_len = x_arr.shape[axis_int]
default_padlen = 3 * max(b_arr.size, a_arr.size)
if x_len <= default_padlen:
padlen_arg = max(0, x_len - 1)
result = scipy_filtfilt(
b_arr,
a_arr,
x_arr,
axis=int(axis),
padtype=padtype if padtype != "None" else None,
padlen=padlen_arg,
method=filtfilt_method,
irlen=int(irlen) if irlen is not None else None
)
return result.tolist()
except Exception as e:
return f"Error: {str(e)}"Online Calculator
The input array of data to be filtered.
The numerator coefficient vector of the filter (1D array in Excel).
The denominator coefficient vector of the filter (1D array in Excel).
The axis along which the filter is applied.
Extension mode for padding at edges.
Number of elements to extend x by at both ends.
Method for handling edges.
Impulse response length for Gustafsson's method.