【发布时间】:2019-10-13 10:11:49
【问题描述】:
假设我有一个 X 和 Y 数组,这样:
X = np.array([1,2,3,4,5,6,7,8,9,10,11,12])
和
Y = np.array([-19.9, -19.6, -17.6, -15.9, -19.9, -18.4, -17.7, -16.6, -19.5, -20.4, -17.6, -15.9])
我得到一个类似的情节:
我可以看到 3 个非常清晰的山峰。我可以使用以下方法拟合这些数据:
# fit polynomial
z = np.polyfit(X1, Y, 8)
f = np.poly1d(z)
# calculate new x's and y's
x_new = np.linspace(X[0], X[-1], 100)
y_new = f(x_new)
我可以得到以下显示一年中信号变化的信息 - 在这种情况下是水稻农业和农业周期数(3 个峰值):
这里我使用 scipy.signal.argrelextrema 来查找曲线的波峰和波谷。但是,要获得一条拟合良好的曲线是一种非常“手动”的方法,我必须先用肉眼解释数据,才能选择多项式阶数。我将在许多数据集(100,000 个)上重复此过程,因此无法每次都手动执行此操作。
此外,我的峰值数量可能会发生变化。事实上,我的最终目标是将我拥有的数据集分类为我可以检测到的峰值数量。也有信号有更多噪声的情况。
我研究了 scipy.signal.find_peaks (和相关算法),但这发现了每个峰值,而不仅仅是主要峰值,尤其是在噪声较大的数据中。我还研究了 savgol 过滤器和高斯过滤器,并且能够得到结果,但通常必须指定多项式等的阶数,这可能会随着峰值的数量而变化。
有没有一种方法可以平滑信号以获得峰值数量的近似值,而无需手动指定多项式阶数等?是否有可用的算法/方法可以在没有太多用户输入的情况下检测一般趋势?
如果有比曲线拟合更好的方法,我也愿意接受替代方法。我担心我得到的结果只会和我输入的一样好,因此任何一般的曲线拟合方法都会产生较差的结果。
【问题讨论】:
-
嗯。关于@james-phillips 的回答,我们可以假设数据是周期性的吗?并且“我可以看到这里有 3 个非常清晰的山峰。”我不得不说不。你会看到两个峰值和一个上升沿,它们可能以峰值或高原结束,甚至发散。您期待第三次高峰,但那是另一回事。
-
@mikuszefski 我将引用原帖:“在这种情况下,水稻农业和农业周期数(3 个峰值)”。此信息似乎与您的评论无关。
-
@JamesPhillips 嗯,“此外,我拥有的峰数可能会改变。”即使没有这个,人们确实期望三个峰值这一事实是一回事,但上面的数据——事实上——并没有显示三个峰值。
-
幸运的是,我的答案中的模型不依赖于峰值的数量,并且目前似乎普遍适用于手头的问题。
-
@JamesPhillips 对此毫无疑问。我只是在评论“显然是 3 个山峰”。尽管问题仍然存在于周期性数据上。很可能但不一定正确的是,这些峰是等距的,对吧?
标签: python scipy curve-fitting