2010-12-16 57 views
4

私はいくつかの定期的なデータを持っていますが、データの量は、期間の の倍数ではありません。このデータをフーリエ解析するにはどうすればよいですか?例:Mathematicaを使って離散データを連続的にフーリエ変換する?

%のテストのためにいくつかのデータを作成してみましょう:

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

%私は今、このデータを受信し、それが上記 式から来たということは考えています。私はちょうど 'データ'から数式を再構築しようとしています。

%フーリエ級数の最初のいくつかの非定数項を見て:周期の数が実際 25000 /(623あるので

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

Mathematica graphics

(6における予想スパイクを示します* 2 * Pi)または約6.38663、これはわかりませんが)。

%6.38663を返すにはどうしたらいいですか? 1つの方法は、データを の任意の倍数のCos [x]で "畳み込む"ことです。

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

%、近 "畳み込み" グラフN = 6:

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

Mathematica graphics

我々は概ね予想されるスパイクを参照。私たちは、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}} 

機能は非常に波状であるため。私たちの間隔(プロット上で視覚的な分析を使用して)を精製して

%、我々は最終的にコンボリューション[]はあまり小刻みていない区間を見つける :

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

Mathematica graphics

とFindMaximum作品:

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

%しかし、このプロセスは、醜い人間​​の介入を必要とし、 コンプconvolve []は本当に遅いです。これを行うより良い方法はありますか?

%データのフーリエ級数を見れば、どういうわけか 「真」のピリオドの数は6.38663です。もちろん、 の実際の結果は6.283185になります。なぜなら、私のデータはより良く適合するからです(私は有限の点で のサンプリングしかないので)。見積もりを取得するには、自己相関を使用して、期間の長さのため

答えて

4

:上記は必ずしも完全に私の質問に答えていませんが は、バージョン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

+0

素晴らしい!私は 'pos'(データを正規化し、最大のフーリエ係数[正規化のために定数項が0であることがわかる])の手順を実行しましたが、fr =行の魔法は何ですか?それは私が探していたものの要点であるようです。 – barrycarter

+1

これはpdata * e^i(...)上でフーリエをやり直しています。フーリエ変換のプロパティを使って補正を計算します。/魔法を実行します。 – tsvikas

3

ルック:

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

離れD = 0から第1の最大のためのスマート検索は、あなたが形成得ることができる最善の見積りかもしれ利用可能なデータ?フーリエ変換機能/アプリケーション/周波数識別のためのMathematicaのヘルプに基づいて

+0

これは、タイトルに記載されている問題を解決するものではありませんが、サンプル中のピリオドの数を調べることに取り組んでいます。 – SEngstrom

+0

これは面白いです、私はそれを検討しています。私は、自己相関が何を行い、どのように機能するのか、これが役立つのか、その答えが何を意味するのかを理解しようとしています。非常に揺れる機能を滑らかなものに変更したことはうれしいことです。 – barrycarter

+0

自己相関はその関数を自己と関連づけています。期間を知らないときに繰り返しパターンを見つけるのに適しています。これは、フーリエ変換でも効率的に行うことができます。 – SEngstrom

0

(* 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 *) 

にチェック私はそれが幾分顕著な を見つけました。

以前、私は( より良い地球フィット感を与えることになっている)Method -> NMinimizeFindFit[]を使用してみましたのだが、それはよく、 はおそらくあなたがFindFit[]インテリジェントな初期値を与えることはできませんので動作しませんでした。

エラー私はバグが出ますが、無関係です。

関連する問題