如何使这个matplotlib图更少嘈杂?

时间:2014-04-07 13:19:04

标签: python matplotlib plot

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

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()

plot

2 个答案:

答案 0 :(得分:5)

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()

enter image description here

答案 1 :(得分:0)

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

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

  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()

enter image description here


  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);

enter image description here

您可能需要对数据尝试多种窗口大小。请注意,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()

enter image description here

可能需要改变 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()

enter image description here

检查 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()

enter image description here

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

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