質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

6744閲覧

フーリエ変換が上手くいかない

Fallout_18

総合スコア124

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/10/20 13:49

編集2018/10/20 15:29

以下のデータをフーリエ変換しています。

date=[0.015625, 0.015625, 0.0625, 0.03515625, 0.09765625, 0.048095703125, 0.10357666015625, 0.07080078125, 0.17388343811035156, 0.13126850128173828, 0.2402327060699463, 0.17284822463989258, 0.26214931160211563, 0.1704627461731434, 0.25162281142547727, 0.15652238787151873, 0.22783483436796814, 0.12990689981961623, 0.1822412261408317, 0.08294962953823415, 0.11317331792179175, 0.0389063490084709, 0.056472000307913106, 0.005247288913015069, 0.009530311218974852, 0.005017450124746858, 0.0015365243368495318, 0.019833988591996476, 0.004779612072076682, 0.03359424834958215, 0.01336109187288527, 0.07296953486201782, 0.07118835430567244, 0.20142962808299264, 0.16327255228856913, 0.2845359127984799, 0.19719090119404797, 0.2510062185645254, 0.13409349144758365, 0.21390037959972297, 0.14605373301204233, 0.22151710012483006, 0.13282687534961274, 0.21408555469675444, 0.11668752550020667, 0.14086572084977306, 0.04890294330442227, 0.0752691630432859, 0.02164490058919605, 0.039182745264478534]

図のように周期的になりますが、途中で切れてしまっているので、窓関数blackmanに通してから、フーリエ変換しましたが、0と50辺りに飛びがでてしまい、また周期的な図と比べても来て欲しい場所の値(26辺り?)にピークがきません。
イメージ説明

python

1from scipy import signal 2itr = 50 3w = signal.blackman(itr) 4#plt.figure() 5windowdate = date[0:itr]*w[0:itr] 6#plt.plot(windowdate) 7f = np.fft.fft(windowdate) 8f_abs =np.abs(f) 9plt.xticks(np.arange(0,itr,10)) 10plt.bar(time,f_abs) 11plt.show()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

fft自体の計算や結果の周波数成分はあっていると思いますが、それをプロットするにあたり横軸の次元を間違って扱っておられるようです。

  • (A)元の波形の横軸

次元は「時間」です。コードではサンプルリングデータの単位を単純に用いてプロットしておられますが、それをそのまま受け入れるなら波形の一周期は25単位時間ほどであるといえます。

  • (B)FFT結果の横軸

次元は「周波数」です。周波数は「単位時間あたりに何周期するか」ということですので、一周期が25単位時間であるならその波の周波数は1/25=0.04ですね。質問者さんは26あたりにスペクトルのピークが出ることを期待しておられますが正しくは周波数1/26=0.038あたりにピークが来ると考えるべきです。

具体的なコードの問題を挙げますと「本来はFFT結果の横軸に周波数を指定すべきところ、元波形の横軸(time)をそのまま設定している」ということになります。

結果のスペクトルの棒グラフをプロットする際に注意すべき点としては

  • 横軸の値は基本周波数(※1)の倍数の数列にする
  • 基本周波数が1より小さいとき、棒グラフの幅が広すぎて見づらくなるためwidthに適当な値を指定する

くらいかと思います。検証のため、サンプリング周波数=1、サンプル数=50として周期25の正弦波を用いてスペクトルをプロットするコードを書いてみました。なお、本件に直接関係ないですが、matplotlibの関数的インターフェース(plt.xxxを呼び出す)ではなくオブジェクト指向的インターフェース(figureやaxesに対してメソッドを呼び出すスタイル)で記述しています。わかりにくかったらすみません。

Python

1import matplotlib.pyplot as plt 2import numpy as np 3 4N = 50 # サンプル数 5Fs = 1 # サンプリング周波数 6Dt = 1 / Fs # サンプル間の時間差 7Fb = Fs / N # 基本周波数 8 9# 元波形の横軸 10ts = np.linspace(0, Dt * N, N, endpoint=False) 11 12# テスト用の波形 13Ft = 0.04 # 周波数(周期=25) 14 15data = np.sin([2 * np.pi * Ft * t for t in ts]) 16 17# 元波形のプロット 18fig = plt.figure() 19ax1 = fig.add_subplot(211) 20ax1.plot(ts, data) 21 22# FFT 23spectrum = np.fft.fft(data) 24abs_spectrum = np.abs(spectrum) 25 26# 周波数成分のプロット 27fs = np.linspace(0, Fb * N, N, endpoint=False) 28ax2 = fig.add_subplot(212) 29ax2.bar(fs, abs_spectrum, width=Fb * 0.8) 30# tick間隔をFtにしたほうが結果がよりはっきりわかるのですが、そうしてしまうと 31# 横軸ラベルが重なってしまい視認できなかったのでFtの倍の間隔にしてあります 32ax2.xaxis.set_ticks(np.arange(0, 1, Ft * 2)) 33 34plt.show()

※1:基本周波数
離散フーリエ変換では、サンプリング周波数Fs、サンプル数Nのとき、計算結果のスペクトルは基本周波数(=Fs/N)の倍数の周波数のものが出てきます。

結果
イメージ説明

この結果を見ると、質問者さんの棒グラフでいえば横軸の値が2のところ(実際は周波数0.04にあたる場所)に期待どおりのスペクトルが出ていることがわかると思います。

投稿2018/10/20 15:47

編集2018/10/20 15:59
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Fallout_18

2018/10/21 02:49

ありがとうございます、一度こちらを参考にチャレンジしてみます。また他のサイトに書いてあったのですが、0.96のところは無視して良いものですよね。
Fallout_18

2018/10/21 02:52

それと少し、話がずれてしまいますが、この窓関数を通してフーリエ変換してもきれいにいかずに、余計なピークがⅩ軸の端にでてしまうのは何故なのでしょう。。。。?
KSwordOfHaste

2018/10/21 03:18 編集

> 0.96のところの値を無視 DFTの結果はサンプリング周波数の1/2(ナイキスト周波数)を中心に左右対称になります。スペクトルの特徴を観察する目的ではグラフの左半分だけに注目すればよいです。 > 余計なピークがX軸の端に それは直流成分であり「窓関数」とは無関係で元信号の平均が0付近にないから出てくるのです。正弦波を見ると信号の平均(直流成分)は0になっていますね。だからDFT結果の周波数0.00の成分が0となるのです。
Fallout_18

2018/10/21 06:25

なるほど、それについては理解しました、ありがとうございます。 質問を出し惜しみしてすいません、上の質問のデータ(周期を10000にしてフーリエ変換した場合、どうやら0.04辺りにピークは来ません、この質問はは新たに設けた方が良いですか?それともこちらでもよろしいでしょうか)、なんどもすいません。
Fallout_18

2018/10/21 07:56

すいません、ちょっともう一回確認してみます。
Fallout_18

2018/10/21 08:51

ただ線が細くて、ピークが見えないだけでした笑 りかいしました、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問