首页 文章

如何改善matplotlib中的曲线拟合?

提问于
浏览
0

我有一组数据,y是角度方向,x是y的每个点的时间戳 .

整个数据集具有许多用于角度方向的段 . 为了进行曲线拟合,我将数据拆分为各自的段,将每个段存储为numpy数组 .

然后,我使用numpy.polyfit找到多项式拟合,以找到适合每个数据段的曲线 . 但是因为我的数据纯粹是实验性的,所以我不知道numpy.polyfit使用哪个多项式度数,因此我迭代一系列多项式度直到找到可能的最高多项式度 .

这是我的代码:

# Experimental data stored in lists: time_aralist and orienrad_aralist
# List stores the segments as arrays

fig = plt.figure()

# Finding curve fit
fittime_aralist, fitorienrad_aralist, fitorienrad_funclist = [], [], []
for j in range(len(time_aralist)):
    z, res, _, _, _ = np.polyfit(time_aralist[j], orienrad_aralist[j], 200, full=True)
    orienrad_func = np.poly1d(z)
    fittime_ara = np.linspace(time_aralist[j][0], time_aralist[j][-1], 10000)
    fitorienrad_ara = orienrad_func(fittime_ara)

    # Appending to list
    fittime_aralist.append(fittime_ara)
    fitorienrad_aralist.append(fitorienrad_ara)
    fitorienrad_funclist.append(orienrad_func)

# Plotting experimental data
for j in range(len(time_aralist)):
    plt.plot(time_aralist[j], orienrad_aralist[j], 'ro')
for j in range(len(fittime_aralist)):
    plt.plot(fittime_aralist[j], fitorienrad_aralist, 'k-')

这就是我的情节 . 以情节为中心的是一段 .

黑线表示尝试的曲线拟合,红点表示实验点 .
enter image description here

如图所示,黑色曲线拟合线并不能很好地拟合数据点 . 我感兴趣的区域是该区域的中间区域,但是尽管使用了最高的多项式度,该区域也不能很好地拟合 .

任何人都可以向我提供任何补充技术,或者更适合数据的替代代码吗?

1 回答

  • 1

    立方插值

    那么数据的三次插值怎么样?

    import numpy as np
    from scipy.interpolate import interp1d
    import matplotlib.pyplot as plt
    
    x = np.linspace(6, 13, num=40)
    y = 3 + 2.*x+np.sin(x)/2.+np.sin(4*x)/3.+ np.random.rand(len(x))/3.
    
    fig, ax = plt.subplots()
    ax.scatter(x,y, s=5, c="crimson")
    
    f = interp1d(x, y, kind='cubic')
    xdens = np.linspace(6, 13, num=400)
    ydens = f(xdens)
    
    ax.plot(xdens, ydens, label="interpolation")
    ax.legend()
    ax2 = ax.twinx()
    yderiv =  np.diff(ydens)/np.diff(xdens)
    ax2.plot(xdens[:-1],yderiv, color="C2", label="derivative")
    
    ax2.legend()
    plt.show()
    

    enter image description here

    样条插值

    使用样条插值可以实现相同的效果 . 优点是 scipy.interpolate.splrep 允许使用参数 s 来平滑结果,它还允许直接评估样条的导数 .

    import numpy as np
    import scipy.interpolate
    import matplotlib.pyplot as plt
    
    x = np.linspace(6, 13, num=40)
    y = 3 + 2.*x+np.sin(x)/2.+np.sin(4*x)/3.+ np.random.rand(len(x))/3.
    
    fig, ax = plt.subplots()
    ax.scatter(x,y, s=5, c="crimson")
    
    tck = scipy.interpolate.splrep(x, y, s=0.4)
    xdens = np.linspace(6, 13, num=400)
    ydens = scipy.interpolate.splev(xdens, tck, der=0)
    
    ax.plot(xdens, ydens, label="spline interpolation")
    ax.legend(loc=2)
    
    ax2 = ax.twinx()
    yderiv = scipy.interpolate.splev(xdens, tck, der=1)
    ax2.plot(xdens, yderiv, color="C2", label="derivative")
    
    ax2.legend(loc=4)
    plt.show()
    

    enter image description here

相关问题