如何用当前数据拟合正弦波?

2024-09-25 16:25:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我收集了一些数据来分析加速度随时间的变化。但是当我编写下面的代码来很好地拟合正弦波时,这就是结果。这是因为我没有足够的数据还是我做错了什么?你知道吗

在这里你可以看到我的图表:

直接绘制测量值(无拟合)

enter image description here

水平和垂直移动拟合(曲线拟合)

enter image description here

通过linspace增加数据

enter image description here

手动操作振幅

enter image description here

编辑:我通过使用linspace函数和绘图增加了数据大小,但我不确定为什么振幅不匹配,是因为要分析的数据很少吗?(我可以手动操纵振幅,但我不明白为什么它不能做到这一点)

我使用的代码

def model(x, a, b):

    return a * np.sin(b * x)

param, parav_cov = cf(model, time, z_values)

array_x = np.linspace(800, 1400, 1000)

fig = plt.figure(figsize = (9, 4))

plt.scatter(time, z_values, color = "#3333cc", label = "Data")

plt.plot(array_x, model(array_x, param[0], param[1], param[2], param[3]), label = "Sin Fit")

Tags: 数据代码modeltimeparamnp时间plt
1条回答
网友
1楼 · 发布于 2024-09-25 16:25:08

我会使用FFT来获得参数的第一个猜测,因为这类事情是高度非线性的,而且curve_fit不太可能在其他方面走得很远。使用FFT的原因是为了获得所涉及频率的初步概念,而不是更多。3Blue1Brown有一个伟大的video on FFTs如果你没有看到它

我使用web plot digitizer从绘图中获取数据,然后将其拉入Python中,并确保它看起来正常:

import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('sinfit2.csv')
print(df.head())

给我:

       x     y
0  809.3   0.3
1  820.0   0.3
2  830.3  19.6
3  839.9  19.6
4  849.6   0.4

我首先用NumPy做了一个基本的FFT(SciPy有完整的fftpack,它更完整,但这里不需要):

import numpy as np
from numpy.fft import fft

d = fft(df.y)

plt.plot(np.abs(d)[:len(d)//2], '.')

np.abs(d)是因为得到了一个包含相位和振幅的复数,[:len(d)//2]是因为(对于实值输入)输出是关于中点对称的,即d[5]==d[-5]。你知道吗

上面说最大的分量是18,我试着用手画出来,看起来还可以:

x = np.linspace(0, np.pi * 2, len(df))

plt.plot(df.x, df.y, '.-', lw=1)
plt.plot(df.x, np.sin(x * 18) * 10 + 10)

我乘以10,加10是因为正弦的范围是(-1,+1),我们需要把它取到(0,20)。你知道吗

接下来,我用一个简化的模型将它们传递给curve_fit,以帮助它:

from scipy.optimize import curve_fit

def model(x, a, b):
    return np.sin(x * a + b) * 10 + 10

(a, b), cov = curve_fit(model, x, df.y, [18, 0])

我再次对* 10 + 10进行硬编码,以获得与您的数据相匹配的范围,从而得到a=17.8b=2.97

最后,我以更高的频率绘制采样的函数,以确保一切正常:

plt.plot(df.x, df.y)
plt.plot(
    np.linspace(810, 1400, 501),
    model(np.linspace(0, np.pi*2, 501), a, b)
)

给我:

validation plot

看起来不错。请注意,您可能希望更改这些参数,使其适合您原来的X,请注意,我的df.x从810开始,因此可能错过了第一点。你知道吗

相关问题 更多 >