我正在尝试平滑此数据集并生成带有误差条的单个代表性曲线。获取数据点的方法是通过相当粗略的步骤离散化的。我没有太多的编程经验,但我正在努力学习。我读到高斯滤波器可能是一个不错的选择。任何帮助,将不胜感激。
以下是一个示例数据集:
Time (min) Non-Normalized Shrinkage Normalized Shrinkage
200 93 1.021978022
202 92 1.010989011
204 92 1.010989011
206 92 1.010989011
208 92 1.010989011
210 92 1.010989011
212 91 1
214 90 0.989010989
216 90 0.989010989
218 90 0.989010989
220 88 0.967032967
222 88 0.967032967
224 87 0.956043956
226 86 0.945054945
228 86 0.945054945
230 86 0.945054945
232 86 0.945054945
234 86 0.945054945
236 85 0.934065934
238 84 0.923076923
240 83 0.912087912
242 83 0.912087912
244 83 0.912087912
246 82 0.901098901
248 83 0.912087912
250 82 0.901098901
252 81 0.89010989
254 81 0.89010989
256 82 0.901098901
258 82 0.901098901
260 79 0.868131868
262 80 0.879120879
264 80 0.879120879
我在某个地方找到了这个代码片段,但我不知道如何实现它,或者它是否是我正在寻找的。 p>
def smoothListGaussian(list,degree=5):
window=degree*2-1
weight=numpy.array([1.0]*window)
weightGauss=[]
for i in range(window):
i=i-degree+1
frac=i/float(window)
gauss=1/(numpy.exp((4*(frac))**2))
weightGauss.append(gauss)
weight=numpy.array(weightGauss)*weight
smoothed=[0.0]*(len(list)-window)
for i in range(len(smoothed)):
smoothed[i]=sum(numpy.array(list[i:i+window])*weight)/sum(weight)
return smoothed
答案 0 :(得分:5)
通常,你会使用一个库,而不是自己实现它。
我将使用scipy.ndimage
代替scipy.signal
。如果你有一个信号处理类,你可能会发现scipy.signal
方法更直观,但如果你没有,它可能会让人感到困惑。 scipy.ndimage
提供了一个直接的,单函数调用gaussian_filter
,而不是必须了解更多的信号处理约定。
以下是一个简单的示例,使用您在问题中发布的数据。这假定您的数据是定期采样的(它是:每2个单位的时间)。
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage
time, _, shrinkage = np.loadtxt('discrete_data.txt', skiprows=1).T
fig, ax = plt.subplots()
ax.plot(time, shrinkage, 'ro')
ax.plot(time, scipy.ndimage.gaussian_filter(shrinkage, 3))
plt.show()
大部分内容相当简单,但您可能会注意到我在3
中指定的scipy.ndimage.gaussian_filter(shrinkage, 3)
的“神奇”值。这是样本中高斯函数的sigma
参数。由于您的数据每2个单位进行一次采样,因此是sigma
个6个单位。
sigma
参数与“钟形曲线”正态分布中的标准偏差完全类似。你做得越大,高斯函数就越宽,你的曲线就越平滑。通过反复试验,对于这个特定的数据集来说,值3看起来是正确的,但是你应该试验并看看你认为最好的东西。
还有一个最后的注意事项:有很多不同的方法可以解决这个问题。高斯滤波器是一种合理的解决方案,但还有很多其他的。如果确切的结果非常重要,您应该比较几种方法,看看哪种方法最适合您的特定数据集。
在评论中,您询问了如何将平滑后的数据保存到文件而不是将其绘制。以下是您可能采用的一种简单示例:
import numpy as np
import scipy.ndimage
time, _, shrinkage = np.loadtxt('discrete_data.txt', skiprows=1).T
smoothed = scipy.ndimage.gaussian_filter(shrinkage, 3)
np.savetxt('smoothed_data.txt', np.c_[time, smoothed])
答案 1 :(得分:0)
如果您的数据集是有限的,我会考虑使用径向基函数研究高斯过程回归 (GPR)。这将获得与使用高斯滤波器平滑函数类似的结果,但有两个重要的好处:
如果您认为这可以解决您的问题,我建议您查看 Python 中的 GPy 库:https://nbviewer.jupyter.org/github/SheffieldML/notebook/blob/master/GPy/index.ipynb