1.joyplotとは
joyplotとは,少し前にtwitterで話題になっていたこんな感じのプロットです.
これは,Rのggjoyというパッケージで簡単にプロットできるようです.pythonにはそれと同様のものはなさそうでした.
ちなみになぜjoyplotというかというと,Joy DivisionというバンドのUnknown Pleasuresというアルバムの表紙が下のような感じだったからjoy plotというらしいです.
なので,このjoyplotを使うときは,これを聞きながらプロットするのが礼儀になっているようです.(嘘です)
2.環境
- Python 3.6.0
- matplotlib (2.0.0)
3.データの生成
このプロットをみて,ベイズ更新やスペクトログラムのプロットに便利そうだなと思ったので,今回はとりあえずスペクトログラムのプロットを試します.
scipyのspectrogramのexampleをそのまま使います.
from scipy import signal
import matplotlib.pyplot as plt
fs = 10e3
N = 1e5
amp = 2 * np.sqrt(2)
noise_power = 0.01 * fs / 2
time = np.arange(N) / float(fs)
mod = 500*np.cos(2*np.pi*0.25*time)
carrier = amp * np.sin(2*np.pi*3e3*time + mod)
noise = np.random.normal(scale=np.sqrt(noise_power), size=time.shape)
noise *= np.exp(-time/5)
data = carrier + noise
f, t, Sxx = signal.spectrogram(data, fs, nperseg=1000, noverlap=900)
4.プロット
stackoverflowのここを参考にしています.
y = Sxx.T
# 数が多いのでスライスする.
y_subset_num = 10
x_subset_num = 20
y = y[0:y_subset_num, 0:x_subset_num]
ny, nx = y.shape
x = f[0:x_subset_num]
y_delta = (y.max() - y.min()) / ny # このy=deltaずつずらしてプロットする.
yticks = [] # yticksの位置を保存する用
fig = plt.figure()
ax = fig.add_subplot(111)
for iy in np.arange(ny):
offset = (ny-iy) * y_delta # 上から順にプロットする
y_value = y[iy] + offset # offset分だけずらす.
ax.plot(x, y_value, color='w', lw=1, zorder=iy)
ax.fill_between(x=x, y1=y_value, y2=offset, alpha=0.5, lw=0, zorder=iy, color="red")
# y_valueの線をプロットし,その下を塗っていく.
yticks.append(offset)
# プロットの上の方が若いので逆順にする.
yticks = yticks[::-1]
ytickslabel = np.arange(len(yticks))[::-1]
ax.set_yticks(yticks)
ax.set_yticklabels(ytickslabel)
ax.set_xlabel("Frequency [Hz]")
plt.show()
こんな感じになります.
綺麗に見せるためには,割と調節芸が必要で.上記コードのy_delta
あたりを変える必要があります.
5.最後に(2017/8/26追加)
seabornのexampleに先月joyplotが追加されているのを発見してしまった.
https://github.com/mwaskom/seaborn/blob/master/examples/kde_joyplot.py
さらに,joypyも発見した.
この二つのいずれかを使うのがいいだろう.