【问题标题】:How to make this matplotlib plot less noisy?如何使这个 matplotlib 绘图不那么嘈杂?
【发布时间】:2014-05-19 18:28:45
【问题描述】:

如何在不考虑每个单独值的情况下用平滑的连续线绘制以下噪声数据?我只想以更好的方式展示行为,而不关心嘈杂和极端值。这是我正在使用的代码:

import numpy
import sys
import matplotlib.pyplot as plt
from scipy.interpolate import spline

dataset = numpy.genfromtxt(fname='data', delimiter=",") 

dic = {}

for d in dataset:
    dic[d[0]] = d[1] 

plt.plot(range(len(dic)), dic.values(),linestyle='-', linewidth=2)

plt.savefig('plot.png')
plt.show()

【问题讨论】:

    标签: python matplotlib plot smoothing


    【解决方案1】:

    previous answer 中,我了解到Savitzky Golay filter,一种特殊类型的低通滤波器,非常适合数据平滑。您希望得到的曲线有多“平滑”是一个偏好问题,这可以通过窗口大小和插值多项式的阶数来调整。使用 sg_filter 的食谱示例:

    import numpy as np
    import sg_filter
    import matplotlib.pyplot as plt
    
    
    # Generate some sample data similar to your post
    X = np.arange(1,1000,1)
    Y = np.log(X**3) + 10*np.random.random(X.shape)
    
    Y2 = sg_filter.savitzky_golay(Y, 101, 3)
    
    plt.plot(X,Y,linestyle='-', linewidth=2,alpha=.5)
    plt.plot(X,Y2,color='r')
    
    plt.show()
    

    【讨论】:

      【解决方案2】:

      有不止一种方法可以做到!

      这里我展示了如何使用各种技术来降低噪音:

      1. 移动平均线
      2. LOWESS 回归
      3. 低通滤波器
      4. 插值

      坚持使用@Hooked 示例数据以保持一致性:

      import numpy as np
      import matplotlib.pyplot as plt
      
      X = np.arange(1, 1000, 1)
      Y = np.log(X ** 3) + 10 * np.random.random(X.shape)
      
      plt.plot(X, Y, alpha = .5)
      plt.show()
      


      1. 移动平均线

      有时您只需要moving average

      例如,使用窗口大小为 100 的 pandas:

      import pandas as pd
      
      df = pd.DataFrame(Y, X)
      df_mva = df.rolling(100).mean()  # moving average with a window size of 100
      
      df_mva.plot(legend = False);
      

      您可能需要对数据尝试几种窗口大小。请注意,df_mva 的前 100 个值将为 NaN,但可以使用 dropna 方法删除这些值。

      pandas rolling function 的使用详情。


      1. LOWESS 回归

      我已成功使用 LOWESS(局部加权散点图平滑)来消除重复测量数据集中的噪声。有关局部回归方法的更多信息,包括 LOWESS 和 LOESS,here。这是一种简单的方法,只需要调整一个参数,根据我的经验,它会产生很好的效果。

      下面是如何使用statsmodels 实现来应用LOWESS 技术:

      import statsmodels.api as sm
      
      y_lowess = sm.nonparametric.lowess(Y, X, frac = 0.3)  # 30 % lowess smoothing
      
      plt.plot(y_lowess[:, 0], y_lowess[:, 1])  # some noise removed
      plt.show()
      

      可能需要更改frac 参数,这是估计每个y 值时使用的数据的一部分。增加frac 值以增加平滑量。 frac 值必须介于 0 和 1 之间。

      关于statsmodels lowess usage的更多详情。


      1. 低通滤波器

      Scipy 提供了一组可能合适的low pass filters

      应用过滤器后:

      from scipy.signal import lfilter
      
      n = 50             # larger n gives smoother curves
      b = [1.0 / n] * n  # numerator coefficients
      a = 1              # denominator coefficient
      y_lf = lfilter(b, a, Y)
      
      plt.plot(X, y_lf)
      plt.show()
      

      查看scipy lfilter documentation,了解有关如何在差分方程中使用分子和分母系数的实施细节。

      scipy.signal package 中还有其他过滤器。


      1. 插值

      最后,这里是radial basis function interpolation的例子:

      from scipy.interpolate import Rbf
      
      rbf = Rbf(X, Y, function = 'multiquadric', smooth = 500)
      y_rbf = rbf(X)
      
      plt.plot(X, y_rbf)
      plt.show()
      

      可以通过增加smooth 参数来实现更平滑的近似。要考虑的替代function 参数包括“cubic”和“thin_plate”。在考虑function 值时,我通常先尝试“thin_plate”,然后再尝试“cubic”;然而,“thin_plate”和“cubic”似乎都在与这个数据集中的噪音作斗争。

      检查scipy docs 中的其他Rbf 选项。 Scipy 提供了其他单变量和多变量插值技术(参见tutorial)。

      【讨论】:

        猜你喜欢
        • 2019-10-07
        • 2019-11-04
        • 1970-01-01
        • 2012-02-15
        • 1970-01-01
        • 2022-06-15
        • 1970-01-01
        • 1970-01-01
        • 2013-01-11
        相关资源
        最近更新 更多