如何在Python中平滑数据?

时间:2015-05-25 18:13:03

标签: python numpy scipy smooth smoothing

我正在尝试使用SciPy的1-D曲线的B样条表示来平滑下面显示的散点图。数据可用here

enter image description here

我使用的代码是:

import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate

data = np.genfromtxt("spline_data.dat", delimiter = '\t')
x = 1000 / data[:, 0]
y = data[:, 1]
x_int = np.linspace(x[0], x[-1], 100)
tck = interpolate.splrep(x, y, k = 3, s = 1)
y_int = interpolate.splev(x_int, tck, der = 0)

fig = plt.figure(figsize = (5.15,5.15))
plt.subplot(111)
plt.plot(x, y, marker = 'o', linestyle='')
plt.plot(x_int, y_int, linestyle = '-', linewidth = 0.75, color='k')
plt.xlabel("X")
plt.ylabel("Y")
plt.show()

我尝试更改样条曲线的顺序和平滑条件,但我没有得到平滑的情节。

B样条插值应该能够平滑数据但出了什么问题?是否有其他方法可以平滑此数据?

3 个答案:

答案 0 :(得分:4)

假设我们正在处理某些现象的嘈杂观测,高斯过程回归也可能是一个不错的选择。关于噪声方差的知识可以包括在参数(块)中,并且可以使用最大似然估计找到其他参数。这是一个如何应用它的简单示例:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.gaussian_process import GaussianProcess

data = np.genfromtxt("spline_data.dat", delimiter='\t')
x = 1000 / data[:, 0]
y = data[:, 1]
x_pred = np.linspace(x[0], x[-1], 100)

# <GP regression>
gp = GaussianProcess(theta0=1, thetaL=0.00001, thetaU=1000, nugget=0.000001)
gp.fit(np.atleast_2d(x).T, y)
y_pred = gp.predict(np.atleast_2d(x_pred).T)
# </GP regression>

fig = plt.figure(figsize=(5.15, 5.15))
plt.subplot(111)
plt.plot(x, y, marker='o', linestyle='')
plt.plot(x_pred, y_pred, linestyle='-', linewidth=0.75, color='k')
plt.xlabel("X")
plt.ylabel("Y")
plt.show()

将给出:

enter image description here

答案 1 :(得分:3)

使用更大的平滑参数。例如,s=1000

tck = interpolate.splrep(x, y, k=3, s=1000)

这会产生:

interpolation

答案 2 :(得分:0)

在您的特定情况下,您还可以尝试将np.linspace函数的最后一个参数更改为较小的数字np.linspace(x[0], x[-1], 10),例如。

演示代码:

import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate

data = np.random.rand(100,2)
tempx = list(data[:, 0])
tempy = list(data[:, 1])
x = np.array(sorted([point*10 + tempx.index(point) for point in tempx]))
y = np.array([point*10 + tempy.index(point) for point in tempy])
x_int = np.linspace(x[0], x[-1], 10)
tck = interpolate.splrep(x, y, k = 3, s = 1)
y_int = interpolate.splev(x_int, tck, der = 0)

fig = plt.figure(figsize = (5.15,5.15))
plt.subplot(111)
plt.plot(x, y, marker = 'o', linestyle='')
plt.plot(x_int, y_int, linestyle = '-', linewidth = 0.75, color='k')
plt.xlabel("X")
plt.ylabel("Y")
plt.show()

您还可以使用pandas中的rolling_mean来平滑数据:

import pandas as pd

data = [...(your data here)...]

smoothendData = pd.rolling_mean(data,5)

rolling_mean的第二个参数是移动平均值(滚动平均值)。您还可以反转数据&quot; data.reverse&#39;,以这种方式获取数据的roll_mean,并将其与前滚滚动均值相结合。另一种选择是指数加权移动平均线: Pandas: Exponential smoothing function for column

或使用带通滤波器: fft bandpass filter in python http://docs.scipy.org/doc/scipy/reference/signal.html