SAVGOL_FILTER

The Savitzky-Golay filter is a digital filter that can be applied to a set of digital data points for the purpose of smoothing the data—that is, to increase the precision of the data without distorting the signal tendency. This is achieved, in a process known as convolution, by fitting successive sub-sets of adjacent data points with a low-degree polynomial by the method of linear least squares.

The filter is particularly effective at preserving higher moments of the signal, such as peak heights and widths, which might be flattened by other smoothing techniques like moving averages.

y_i = \sum_{j=-k}^k C_j x_{i+j}

where C_j are the filter coefficients derived from the polynomial fit.

Excel Usage

=SAVGOL_FILTER(x, window_length, polyorder, deriv, delta, axis, savgol_mode, cval)
  • x (list[list], required): The data to be filtered (Excel range).
  • window_length (int, required): The length of the filter window (must be positive and odd).
  • polyorder (int, required): The order of the polynomial used to fit the samples.
  • deriv (int, optional, default: 0): The order of the derivative to compute.
  • delta (float, optional, default: 1): The spacing of the samples (used if deriv > 0).
  • axis (int, optional, default: -1): The axis along which the filter is applied.
  • savgol_mode (str, optional, default: “interp”): Extension mode for padded signal.
  • cval (float, optional, default: 0): Value to fill past edges if mode is ‘constant’.

Returns (list[list]): The filtered data as a 2D array.

Example 1: Basic smoothing

Inputs:

x window_length polyorder
2 2 5 2 1 0 1 4 9 5 2

Excel formula:

=SAVGOL_FILTER({2,2,5,2,1,0,1,4,9}, 5, 2)

Expected output:

Result
1.65714 3.17143 3.54286 2.85714 0.657143 0.171429 1 4 9
Example 2: Nearest mode

Inputs:

x window_length polyorder savgol_mode
2 2 5 2 1 0 1 4 9 5 2 nearest

Excel formula:

=SAVGOL_FILTER({2,2,5,2,1,0,1,4,9}, 5, 2, "nearest")

Expected output:

Result
1.74286 3.02857 3.54286 2.85714 0.657143 0.171429 1 4.6 7.97143
Example 3: First derivative

Inputs:

x window_length polyorder deriv
0 1 4 9 16 5 2 1

Excel formula:

=SAVGOL_FILTER({0,1,4,9,16}, 5, 2, 1)

Expected output:

Result
-4.4406e-15 2 4 6 8

Python Code

Show Code
import numpy as np
from scipy.signal import savgol_filter as scipy_savgol

def savgol_filter(x, window_length, polyorder, deriv=0, delta=1, axis=-1, savgol_mode='interp', cval=0):
    """
    Apply a Savitzky-Golay filter to a signal array for smoothing.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.savgol_filter.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        x (list[list]): The data to be filtered (Excel range).
        window_length (int): The length of the filter window (must be positive and odd).
        polyorder (int): The order of the polynomial used to fit the samples.
        deriv (int, optional): The order of the derivative to compute. Default is 0.
        delta (float, optional): The spacing of the samples (used if deriv > 0). Default is 1.
        axis (int, optional): The axis along which the filter is applied. Default is -1.
        savgol_mode (str, optional): Extension mode for padded signal. Valid options: Mirror, Constant, Nearest, Wrap, Interp. Default is 'interp'.
        cval (float, optional): Value to fill past edges if mode is 'constant'. Default is 0.

    Returns:
        list[list]: The filtered data as a 2D array.
    """
    try:
        def to2d(x):
            return [[x]] if not isinstance(x, list) else x

        x_arr = np.array(to2d(x))

        # Handle potential conversion issues
        if x_arr.dtype.kind not in 'iuf':
            # Try to convert to float, ignoring non-numeric
            x_flat = x_arr.flatten()
            cleaned = []
            for val in x_flat:
                try:
                    cleaned.append(float(val))
                except (TypeError, ValueError):
                    cleaned.append(0.0) # Or should we use nan? filter usually fails on nan.
            x_arr = np.array(cleaned).reshape(x_arr.shape)

        result = scipy_savgol(
            x_arr, 
            window_length=int(window_length), 
            polyorder=int(polyorder), 
            deriv=int(deriv), 
            delta=float(delta), 
            axis=int(axis), 
            mode=savgol_mode, 
            cval=float(cval)
        )

        return result.tolist()
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

The data to be filtered (Excel range).
The length of the filter window (must be positive and odd).
The order of the polynomial used to fit the samples.
The order of the derivative to compute.
The spacing of the samples (used if deriv > 0).
The axis along which the filter is applied.
Extension mode for padded signal.
Value to fill past edges if mode is 'constant'.