我试图使用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()
这两个拐点在附图中以红线显示。但是,他们的位置似乎不对。第一个拐点应该接近黑色箭头指示的区域。我该如何解决这个问题?
此外,这是差异图:
plt.axvline(np.gradient(arr[:365]).argmax())
如您所见,代码表现为编码,即它找到数组的np.diff的argmax。但是,我希望找到一个接近第110天左右的位置,即大约到argmax的一半。
- 编辑 -
此外,这是另一个显示原始数据和拟合曲线的图(使用二次函数)。
答案 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)
我们也可以用数字来解决最大值:
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])