Search code examples
pythonperformancescipyfilteringnoise-reduction

How to compare scipy noise filters?


I need to reduce my noise like behavior in my data. I tried one of the method called Savitzky-Golay Filter . On the other hand, I need to find fastest method, because the filtering algorithm will be in the most running script in my code.

I am not familiar with the signal processing methods. Can you suggest faster methods and usage of them briefly?

I do not need complex structure like low-pass, high-pass etc (I know there are thousands of them). As fast as possible smoothening method is what I want to use.

Here my test script:

import numpy as np
import matplotlib.pyplot as plt

noisyData=np.array([
   2.77741650e+43,   1.30016392e+42,   8.05792443e+42,   1.74277713e+43,
   2.33814198e+43,   6.75553976e+42,   2.56642073e+43,   4.71467220e+43,
   4.25047666e+43,   3.07095152e+43,   7.30694187e+43,   7.54411548e+43,
   1.29555422e+43,   8.09272000e+42,   9.18193162e+43,   2.25447063e+44,
   3.43044832e+41,   7.02901256e+43,   2.54438379e+43,   8.72303015e+43,
   7.80333557e+42,   7.55039871e+43,   7.70164773e+43,   4.38740319e+43,
   8.43139041e+43,   6.12168640e+43,   5.64352020e+43,   3.63824769e+42,
   2.35296604e+43,   4.66272666e+43,   5.03660902e+44,   1.65071897e+44,
   2.81055925e+44,   1.46401444e+44,   5.44407940e+43,   4.50672710e+43,
   1.60833084e+44,   1.68038069e+44,   1.08588606e+44,   7.00867980e+43])

xAxis=np.arange(len(noisyData))

# ------------- Savitzky-Golay Filter ---------------------
windowLength = len(xAxis) - 5 
polyOrder = 6

from scipy.signal import savgol_filter

# Function
def set_SavgolFilter(noisyData,windowLength,polyOrder):
    return savgol_filter(noisyData, windowLength, polyOrder)

plt.plot(xAxis,noisyData,alpha=0.5)
plt.plot(xAxis,set_SavgolFilter(noisyData,windowLength,polyOrder))

# ------------- Time Comparison ----------------------
import time
start_time = time.time()
for i in range(50):
    savgolfilter1 = set_SavgolFilter(noisyData,windowLength,polyOrder)
print(" %s seconds " % (time.time() - start_time))

# === OTHER METHODS WILL BE HERE

Solution

  • Unless you really need polynomial-based smoothing, Savitzky-Golay does not have any particular advantages. It's basically a bad lowpass filter. For more details, see https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=5888646

    Using a basic Butterworth lowpass filter instead:

    from scipy.signal import butter, filtfilt
    b, a = butter(5, .2)
    datafilt = filtfilt(b, a, noisyData)
    

    The filtfilt call seems to be several times faster than savgol_filter. How much faster do you need? Using lfilter from scipy is at least 10 times faster, but the result will be delayed with respect to the input signal.