让我们假设我们有一个数据集,它大概是

import numpy as np
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2

Therefore we have a variation of 20% of the dataset. My first idea was to use the UnivariateSpline function of scipy, but the problem is that this does not consider the small noise in a good way. If you consider the frequencies, the background is much smaller than the signal, so a spline only of the cutoff might be an idea, but that would involve a back and forth fourier transformation, which might result in bad behaviour. Another way would be a moving average, but this would also need the right choice of the delay.

有什么提示/书籍或链接可以解决这个问题吗?


当前回答

使用移动平均线,一种快速的方法(也适用于非双射函数)是

def smoothen(x, winsize=5):
    return np.array(pd.Series(x).rolling(winsize).mean())[winsize-1:]

此代码基于https://towardsdatascience.com/data-smoothing-for-data-science-visualization-the-goldilocks-trio-part-1-867765050615。文中还讨论了更先进的解决方案。

其他回答

你也可以用这个:

def smooth(scalars, weight = 0.8):  # Weight between 0 and 1
        return [scalars[i] * weight + (1 - weight) * scalars[i+1] for i in range(len(scalars)) if i < len(scalars)-1]

我喜欢Savitzky-Golay滤镜。它使用最小二乘将数据的一个小窗口回归到一个多项式上,然后使用多项式来估计窗口中心的点。最后,窗口向前移动一个数据点,然后重复这个过程。这一直持续到每个点都相对于它的邻居进行了最佳调整。即使是非周期和非线性源的噪声样本,它也能很好地工作。

下面是一个完整的食谱示例。请参阅下面的代码,了解它使用起来有多简单。注意:我省略了定义savitzky_golay()函数的代码,因为您可以从上面链接的烹饪书示例中复制/粘贴它。

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
yhat = savitzky_golay(y, 51, 3) # window size 51, polynomial order 3

plt.plot(x,y)
plt.plot(x,yhat, color='red')
plt.show()

更新:我注意到我链接的食谱例子已经被撤下了。幸运的是,正如@dodohjk(感谢@bicarlsen提供的更新链接)指出的那样,Savitzky-Golay过滤器已经被合并到SciPy库中。 要使用SciPy源代码调整上面的代码,输入:

from scipy.signal import savgol_filter
yhat = savgol_filter(y, 51, 3) # window size 51, polynomial order 3

如果您正在绘制时间序列图,并且如果您已经使用mtplotlib来绘制图形,那么请使用 中值方法平滑图

smotDeriv = timeseries.rolling(window=20, min_periods=5, center=True).median()

时间序列是您传递的数据集,您可以更改窗口大小以更平滑。

在scipy中有一个简单的函数。Ndimage也适用于我:

from scipy.ndimage import uniform_filter1d

y_smooth = uniform_filter1d(y,size=15)

使用移动平均线,一种快速的方法(也适用于非双射函数)是

def smoothen(x, winsize=5):
    return np.array(pd.Series(x).rolling(winsize).mean())[winsize-1:]

此代码基于https://towardsdatascience.com/data-smoothing-for-data-science-visualization-the-goldilocks-trio-part-1-867765050615。文中还讨论了更先进的解决方案。