matplotlib
前回、NumPyでヒストグラムのビンを任意に作成する方法(np.ditigize)を紹介しました。
あわせて読みたい


【NumPy】ヒストグラムのビンを任意に作成する方法(np.ditigize)[Python]
NumPy 前回、NumPyで配列を連結する方法(np.hstack、np.vstack、np.dstack、np.concatenate、np.block)を紹介しました。 今回はNumPyでヒストグラムのビンを任意に作…
今回はmatplotlibのspecgramを使って時間周波数解析をする方法を紹介します。
時間周波数解析に関してはSciPyを使って行う方法を前に紹介していますので、良かったらどうぞ。
あわせて読みたい


【SciPy】短時間フーリエ変換(STFT:Short-time Fourier Transform)による時間周波数解析[Python]
短時間フーリエ変換 前回、Pythonで時間変化のあるランダムな波形を作成する方法を紹介しました。 今回はその時間変化のあるランダムな波形を使って、経時的な変化を視…
それでは始めていきましょう。
specgramの使い方
specgramを使い、時間周波数解析の結果をグラフ化するには「plt.specgram(波データ, サンプリングレート)」とします。
簡単なsin 波を使って試してみましょう。
import matplotlib.pyplot as plt
import numpy as np
fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time)
fig = plt.figure()
plt.clf()
plt.specgram(y, Fs=fs)
plt.xlabel("Time")
plt.ylabel("Frequency")
plt.show()
実行結果

20 Hzと100 Hzのsin波を合成した場合はこの様になります。
import matplotlib.pyplot as plt
import numpy as np
fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)
fig = plt.figure()
plt.clf()
plt.specgram(y, Fs=fs)
plt.xlabel("Time")
plt.ylabel("Frequency")
plt.show()
実行結果

カラーマップの変更方法
plt.specgramのオプション引数はいくつかあるのですが、特によく使うものとしてカラーマップのオプション引数があります。
カラーマップを変更するには「cmap=カラーマップ」を追加します。
import matplotlib.pyplot as plt
import numpy as np
fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)
fig = plt.figure()
plt.clf()
plt.specgram(y, Fs=fs, cmap="plasma")
plt.xlabel("Time")
plt.ylabel("Frequency")
plt.show()
実行結果

分解能の変更方法
出力する画像の分解能を変更するには「NFFT」と「noverlap」のオプション引数を変更します。
デフォルトはそれぞれ256と128です。
それぞれ値を小さくするとこんな感じになります。
import matplotlib.pyplot as plt
import numpy as np
fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)
fig = plt.figure()
plt.clf()
plt.specgram(y, Fs=fs, NFFT=64, noverlap=16)
plt.xlabel("Time")
plt.ylabel("Frequency")
plt.show()
実行結果

逆に値を大きくするとこんな感じです。
import matplotlib.pyplot as plt
import numpy as np
fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)
fig = plt.figure()
plt.clf()
plt.specgram(y, Fs=fs, NFFT=512, noverlap=256)
plt.xlabel("Time")
plt.ylabel("Frequency")
plt.show()
実行結果

さらに値を大きくしてNFFTがデータ数よりも大きくなった場合、警告が出ます。
import matplotlib.pyplot as plt
import numpy as np
fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)
fig = plt.figure()
plt.clf()
plt.specgram(y, Fs=fs, NFFT=1024, noverlap=512)
plt.xlabel("Time")
plt.ylabel("Frequency")
plt.show()
実行結果
/var/folders/sp/hg7p80kx22s7vct7yb0zl5cm0000gn/T/ipykernel_3389/
3366260405.py:11: UserWarning: Only one segment is calculated since
parameter NFFT (=1024) >= signal length (=1000).
plt.specgram(y, Fs=fs, NFFT=1024, noverlap=512)

またNFFTはnoverlapより必ず大きい値である必要があります。
noverlapがNFFTと同じ値、もしくはNFFTより大きな値になった場合はエラーとなります。
import matplotlib.pyplot as plt
import numpy as np
fs = 1000
time = np.arange(0, 1, 1/fs)
y = np.sin(20*2*np.pi*time) + np.sin(100*2*np.pi*time)
fig = plt.figure()
plt.clf()
plt.specgram(y, Fs=fs, NFFT=64, noverlap=64)
plt.xlabel("Time")
plt.ylabel("Frequency")
plt.show()
実行結果
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[60], line 11
8 fig = plt.figure()
9 plt.clf()
---> 11 plt.specgram(y, Fs=fs, NFFT=64, noverlap=64)
13 plt.xlabel("Time")
14 plt.ylabel("Frequency")
(中略)
ValueError: noverlap must be less than NFFT
次回はmatplotlibで積み上げの折れ線グラフを作成する方法(plt.stackplot)を紹介します。
それでは今回はこんな感じで。
コメント