【问题标题】:Smoothing a discrete data set平滑离散数据集
【发布时间】:2015-01-01 21:11:44
【问题描述】:

我正在尝试对此数据集进行平滑处理,并生成一条带有误差线的具有代表性的曲线。获取数据点的方法以相当粗略的步骤离散化。我没有太多的编程经验,但正在努力学习。我读到高斯滤波器可能是一个不错的选择。任何帮助,将不胜感激。

这是一个示例数据集:

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

我在网上某处找到了这段代码 sn-p,但我不知道如何实现它,也不知道它是否是我正在寻找的。​​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 

【问题讨论】:

    标签: python numpy scipy curve-fitting smoothing


    【解决方案1】:

    通常,您会为此使用一个库,而不是自己实现它。

    我将为此使用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()
    

    其中大部分内容相当简单,但您可能会注意到我在scipy.ndimage.gaussian_filter(shrinkage, 3) 中指定的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])
    

    【讨论】:

    • 非常感谢。我将尝试实现这一点。确切的解决方案并不重要,更多的是出于演示目的。我有来自不同样本的多条曲线,我将把它们绘制在另一条之上。
    • 遗憾的是,我在使用 matplotlib.pyplot 库时遇到了一些困难。 ImportError: No module named matplotlib.pyplot 我尝试将序言更改为指向 matplotlib 的安装位置,但这似乎不起作用。实际上,只得到一个高斯数据点的图,然后我可以绘制它会更有益。我该怎么做?
    • @SeattleFreezer - 你是如何安装 matplotlib 的?是否有可能您安装了多个 python 可执行文件,并且您为一个安装了 matplotlib 而没有为另一个安装?
    • 我用easy_install matplolib 安装了matplotlib 这绝对是可能的。我有一台 mac,在过去的一年里,我一直在用 python 处理不同的东西。我想要一个干净的安装,但从我读过的内容来看,如果我没有正确安装,我很容易把事情搞砸。
    • 可能发生的事情是easy_install 指向一个python 可执行文件,而您在运行脚本时正在调用另一个可执行文件。检查which python 的输出,并调用安装matplotlib 的python 可执行文件的完整路径(它不会是which python 输出的内容)。例如,如果您使用 Anaconda,并将其安装在主目录中,则可以调用 $HOME/anaconda/bin/python
    【解决方案2】:

    如果您的数据集是有限的,我会考虑使用径向基函数研究高斯过程回归 (GPR)。这将获得与使用高斯滤波器平滑函数类似的结果,但有两个重要的好处:

    1. 它可以自动选择过滤器的“神奇”标准差,这意味着输出估计将最适合您的数据。
    2. 它将为您估计其输出与您的数据匹配的可信度 - 为您提供最佳误差线。

    以下是 GPR 用于估计正弦波的示例:

    如果您认为这可以解决您的问题,我建议您查看 Python 中的 GPy 库:https://nbviewer.jupyter.org/github/SheffieldML/notebook/blob/master/GPy/index.ipynb

    【讨论】:

      猜你喜欢
      • 2014-08-04
      • 1970-01-01
      • 1970-01-01
      • 2020-02-16
      • 2022-01-20
      • 2014-10-10
      • 2016-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多