使用python修复拐点估计

时间:2016-03-06 16:26:10

标签: python numpy scipy

我试图使用python在曲线上找到拐点。曲线的数据如下:https://www.dropbox.com/s/rig8frgewde8i5n/fitted.txt?dl=0。请注意,曲线已经适合原始数据。原始数据可在此处获取:https://www.dropbox.com/s/1lskykdi1ia1lu7/ww.txt?dl=0

import numpy as np
# Read in array from text file
arr = np.loadtxt(path_to_file)

inflexion_point_1 = np.diff(arr).argmin()
inflexion_point_2 = np.diff(arr).argmax()

这两个拐点在附图中以红线显示。但是,他们的位置似乎不对。第一个拐点应该接近黑色箭头指示的区域。我该如何解决这个问题?

enter image description here

此外,这是差异图:

plt.axvline(np.gradient(arr[:365]).argmax())

如您所见,代码表现为编码,即它找到数组的np.diff的argmax。但是,我希望找到一个接近第110天左右的位置,即大约到argmax的一半。

enter image description here

- 编辑 -

此外,这是另一个显示原始数据和拟合曲线的图(使用二次函数)。

enter image description here

1 个答案:

答案 0 :(得分:5)

是否有任何理由不直接在渐变上使用单变量样条线?

from scipy.interpolate import UnivariateSpline

#raw data
data = np.genfromtxt('ww.txt')

plt.plot(np.gradient(data), '+')

spl = UnivariateSpline(np.arange(len(data)), np.gradient(data), k=5)
spl.set_smoothing_factor(1000)
plt.plot(spl(np.arange(len(data))), label='Smooth Fct 1e3')
spl.set_smoothing_factor(10000)
plt.plot(spl(np.arange(len(data))), label='Smooth Fct 1e4')
plt.legend(loc='lower left')

max_idx = np.argmax(spl(np.arange(len(data))))
plt.vlines(max_idx, -5, 9, linewidth=5, alpha=0.3)

enter image description here

我们也可以用数字来解决最大值:

In [122]:

import scipy.optimize as so
F = lambda x: -spl(x)
so.fmin(F, 102)
Optimization terminated successfully.
         Current function value: -3.339112
         Iterations: 20
         Function evaluations: 40
Out[122]:
array([ 124.91303558])