使用 Mathematica 对离散数据进行连续傅里叶变换?

发布于 2024-10-08 15:16:30 字数 1712 浏览 10 评论 0原文

我有一些周期性数据,但数据量不是的倍数 期间。我如何傅里叶分析这些数据?示例:

% 让我们创建一些数据进行测试:

data = Table[N[753+919*Sin[x/623-125]], {x,1,25000}] 

% 我现在收到此数据,但不知道它来自 上面的公式。我试图仅根据“数据”重建公式。

% 查看傅立叶级数的前几个非常数项:

ListPlot[Table[Abs[Fourier[data]][[x]], {x,2,20}], PlotJoined->True, 
 PlotRange->All] 

Mathematicagraphics

显示预期峰值为 6(因为周期数确实是 25000/(623*2*Pi) 或大约 6.38663,尽管我们不知道这一点)。

% 现在,我如何取回 6.38663?一种方法是将数据与 Cos[x] 的任意倍数。

convolve[n_] := Sum[data[[x]]*Cos[n*x], {x,1,25000}] 

% 并绘制 n=6 附近的“卷积”:

Plot[convolve[n],{n,5,7}, PlotRange->All] 

Mathematicagraphics

我们看到大致在预期位置出现峰值。

% 我们尝试 FindMaximum:

FindMaximum[convolve[n],{n,5,7}] 

但结果无用且不准确:

FindMaximum::fmmp:  
   Machine precision is insufficient to achieve the requested accuracy or 
    precision. 

Out[119]= {98.9285, {n -> 5.17881}} 

因为该函数非常不稳定。

% 通过细化我们的区间(使用图上的视觉分析),我们 最终找到一个 convolve[] 不会摆动太多的区间:

Plot[convolve[n],{n,6.2831,6.2833}, PlotRange->All] 

Mathematicagraphics

和 FindMaximum 有效:

FindMaximum[convolve[n],{n,6.2831,6.2833}] // FortranForm 
List(1.984759605826571e7,List(Rule(n,6.2831853071787975))) 

% 但是,这个过程很丑陋,需要人工干预,并且 计算 convolve[] 确实很慢。有更好的方法吗?

% 看看数据的傅里叶级数,我能以某种方式推测出 “真实”周期数是 6.38663?当然,实际结果 将是 6.283185,因为我的数据更适合(因为我只是 在有限数量的点上采样)。

I have some periodic data, but the amount of data is not a multiple of
the period. How can I Fourier analyze this data? Example:

% Let's create some data for testing:

data = Table[N[753+919*Sin[x/623-125]], {x,1,25000}] 

% I now receive this data, but have no idea that it came from the
formula above. I'm trying to reconstruct the formula just from 'data'.

% Looking at the first few non-constant terms of the Fourier series:

ListPlot[Table[Abs[Fourier[data]][[x]], {x,2,20}], PlotJoined->True, 
 PlotRange->All] 

Mathematica graphics

shows an expected spike at 6 (since the number of periods is really
25000/(623*2*Pi) or about 6.38663, though we don't know this).

% Now, how do I get back 6.38663? One way is to "convolve" the data with
arbitrary multiples of Cos[x].

convolve[n_] := Sum[data[[x]]*Cos[n*x], {x,1,25000}] 

% And graph the "convolution" near n=6:

Plot[convolve[n],{n,5,7}, PlotRange->All] 

Mathematica graphics

we see a spike roughly where expected.

% We try FindMaximum:

FindMaximum[convolve[n],{n,5,7}] 

but the result is useless and inaccurate:

FindMaximum::fmmp:  
   Machine precision is insufficient to achieve the requested accuracy or 
    precision. 

Out[119]= {98.9285, {n -> 5.17881}} 

because the function is very wiggly.

% By refining our interval (using visual analysis on the plots), we
finally find an interval where convolve[] doesn't wiggle too much:

Plot[convolve[n],{n,6.2831,6.2833}, PlotRange->All] 

Mathematica graphics

and FindMaximum works:

FindMaximum[convolve[n],{n,6.2831,6.2833}] // FortranForm 
List(1.984759605826571e7,List(Rule(n,6.2831853071787975))) 

% However, this process is ugly, requires human intervention, and
computing convolve[] is REALLY slow. Is there a better way to do this?

% Looking at the Fourier series of the data, can I somehow divine the
"true" number of periods is 6.38663? Of course, the actual result
would be 6.283185, since my data fits that better (because I'm only
sampling at a finite number of points).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

乄_柒ぐ汐 2024-10-15 15:16:30

基于 Mathematica 的傅立叶函数/应用/频率识别帮助:
检查版本 7

n = 25000;
data = Table[N[753 + 919*Sin[x/623 - 125]], {x, 1, n}];
pdata = data - Total[data]/Length[data];
f = Abs[Fourier[pdata]];
pos = Ordering[-f, 1][[1]]; (*the position of the first Maximal value*)  
fr = Abs[Fourier[pdata Exp[2 Pi I (pos - 2) N[Range[0, n - 1]]/n], 
   FourierParameters -> {0, 2/n}]];
frpos = Ordering[-fr, 1][[1]];

N[(pos - 2 + 2 (frpos - 1)/n)]

返回 6.37072

Based on Mathematica help for the Fourier function / Applications / Frequency Identification:
Checked on version 7

n = 25000;
data = Table[N[753 + 919*Sin[x/623 - 125]], {x, 1, n}];
pdata = data - Total[data]/Length[data];
f = Abs[Fourier[pdata]];
pos = Ordering[-f, 1][[1]]; (*the position of the first Maximal value*)  
fr = Abs[Fourier[pdata Exp[2 Pi I (pos - 2) N[Range[0, n - 1]]/n], 
   FourierParameters -> {0, 2/n}]];
frpos = Ordering[-fr, 1][[1]];

N[(pos - 2 + 2 (frpos - 1)/n)]

returns 6.37072

从﹋此江山别 2024-10-15 15:16:30

使用自相关查找周期长度以获得估计值:

autocorrelate[data_, d_] := 
 Plus @@ (Drop[data, d]*Drop[data, -d])/(Length[data] - d)

ListPlot[Table[{d, autocorrelate[data, d]}, {d, 0, 5000, 100}]]

Mathematicagraphics

智能搜索远离 d=0 的第一个最大值可能是您可以从可用数据中获得的最佳估计?

Look for the period length using autocorrelation to get an estimate:

autocorrelate[data_, d_] := 
 Plus @@ (Drop[data, d]*Drop[data, -d])/(Length[data] - d)

ListPlot[Table[{d, autocorrelate[data, d]}, {d, 0, 5000, 100}]]

Mathematica graphics

A smart search for the first maximum away from d=0 may be the best estimate you can get form the available data?

神爱温柔 2024-10-15 15:16:30

(* the data *) 

data = Table[N[753+919*Sin[x/623-125]], {x,1,25000}]; 

(* Find the position of the largest Fourier coefficient, after 
removing the last half of the list (which is redundant) and the 
constant term; the [[1]] is necessary because Ordering returns a list *) 

f2 = Ordering[Abs[Take[Fourier[data], {2,Round[Length[data]/2+1]}]],-1][[1]] 

(* Result: 6 *) 

(* Directly find the least squares difference between all functions of 
the form a+b*Sin[c*n-d], with intelligent starting values *) 

sol = FindMinimum[Sum[((a+b*Sin[c*n-d]) - data[[n]])^2, {n,1,Length[data]}], 
{{a,Mean[data]},{b,(Max[data]-Min[data])/2},{c,2*f2*Pi/Length[data]},d}] 

(* Result (using //InputForm):  

FindMinimum::sszero:  
   The step size in the search has become less than the tolerance prescribed by 
   the PrecisionGoal option, but the gradient is larger than the tolerance 
   specified by the AccuracyGoal option. There is a possibility that the method 
   has stalled at a point that is not a local minimum. 

{2.1375902350021628*^-19, {a -> 753., b -> -919., c -> 0.0016051364365971107,  
  d -> 2.477886509998064}} 

*) 


(* Create a table of values for the resulting function to compare to 'data' *) 

tab = Table[a+b*Sin[c*x-d], {x,1,Length[data]}] /. sol[[2]]; 

(* The maximal difference is effectively 0 *) 

Max[Abs[data-tab]] // InputForm 

(* Result: 7.73070496506989*^-12 *) 

虽然上面不一定完全回答我的问题,但我发现了
有点了不起。

早些时候,我尝试使用 FindFit[]Method ->; NMinimize (即
应该能够提供更好的全局拟合),但这效果不佳,
可能是因为您无法给出 FindFit[] 智能起始值。

我收到的错误让我烦恼,但似乎无关紧要。


(* the data *) 

data = Table[N[753+919*Sin[x/623-125]], {x,1,25000}]; 

(* Find the position of the largest Fourier coefficient, after 
removing the last half of the list (which is redundant) and the 
constant term; the [[1]] is necessary because Ordering returns a list *) 

f2 = Ordering[Abs[Take[Fourier[data], {2,Round[Length[data]/2+1]}]],-1][[1]] 

(* Result: 6 *) 

(* Directly find the least squares difference between all functions of 
the form a+b*Sin[c*n-d], with intelligent starting values *) 

sol = FindMinimum[Sum[((a+b*Sin[c*n-d]) - data[[n]])^2, {n,1,Length[data]}], 
{{a,Mean[data]},{b,(Max[data]-Min[data])/2},{c,2*f2*Pi/Length[data]},d}] 

(* Result (using //InputForm):  

FindMinimum::sszero:  
   The step size in the search has become less than the tolerance prescribed by 
   the PrecisionGoal option, but the gradient is larger than the tolerance 
   specified by the AccuracyGoal option. There is a possibility that the method 
   has stalled at a point that is not a local minimum. 

{2.1375902350021628*^-19, {a -> 753., b -> -919., c -> 0.0016051364365971107,  
  d -> 2.477886509998064}} 

*) 


(* Create a table of values for the resulting function to compare to 'data' *) 

tab = Table[a+b*Sin[c*x-d], {x,1,Length[data]}] /. sol[[2]]; 

(* The maximal difference is effectively 0 *) 

Max[Abs[data-tab]] // InputForm 

(* Result: 7.73070496506989*^-12 *) 

Although the above doesn't necessarily fully answer my question, I found it
somewhat remarkable.

Earlier, I'd tried using FindFit[] with Method -> NMinimize (which is
supposed to give a better global fit), but that didn't work well,
possibly because you can't give FindFit[] intelligent starting values.

The error I get bugs me but appears to be irrelevant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文