【问题标题】:How to improve curve fitting in matplotlib?如何改进 matplotlib 中的曲线拟合?
【发布时间】:2017-07-23 16:10:48
【问题描述】:

我有一组数据,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-')

这就是我的情节的样子。图中的中心是一段。

黑线给出了尝试的曲线拟合,红点是实验点。

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

谁能为我提供任何补充技术,或者可以更好地拟合数据的替代代码?

【问题讨论】:

  • 问题是,你有适合数据的模型吗?或者你只是想通过这些点产生一条漂亮的线? IE。你需要一个fit吗?如果是这样,则需要知道要考虑哪些可能的拟合函数。如果不是,则根本不应该使用配件。
  • 我需要曲线拟合,因为我对数据的一阶导数感兴趣。我不知道要拟合的模型。
  • 我的意思是,如果你没有模型,就没有什么可以适应的。这里唯一的目标是密集的一阶导数吗?
  • 是的,这是主要目标。

标签: python numpy matplotlib


【解决方案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()

样条插值

同样可以通过样条插值来实现。优点是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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    相关资源
    最近更新 更多