やりたいこと
時間が行のインデックスに、オクターブバンドの中心周波数が列のインデックスになってるようなDataFrameを使って3Dグラフを描きたいです。
今回はESC-50の音声データを使用しており、オクターブ解析した後のデータは以下のような形で格納されています。
index 列に時間が格納されており、各列の列名にはオクターブバンドの中心周波数が格納されています。
なお、環境としてはGoogle Colaboratoryを使用しています。
コード例
以下のコードで所望の動きを実現することができました。
上手くいくと次のような3Dのグラフを描画することができます。
書き方が2通りありますが、自分の流派の方を参考にしてください。
書き方の違いは最後に補足します。
pyplotインターフェースを使う書き方
import matplotlib.pyplot as plt plt.pcolor(df.index, np.arange(0, len(df.columns)), df.T, cmap=cm.jet, vmin = -80, vmax = -20) plt.yticks(np.arange(0, len(df.columns), 4), df.columns[::4]) plt.colorbar()
データ自体はdfに格納されているものとします。
ポイントはY軸の値には各オクターブバンドの中心周波数を与えるのではなく、一度0~バンド数で指定した後に、改めてY軸のラベルを置き換えているという点です(3行目のnp.arange)。
plt.yticksのところがラベルを置き換えているところに相当します。
ちなみに直接Y軸の値としてオクターブバンドの中心周波数を与えるとうまくいきませんでした。
ラベルは4個飛ばしで描画してますが、見栄えがそれっぽかったので4個飛ばしにしているだけで、特に理由はないです。
オブジェクト指向インターフェースを使う書き方
import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(1,1,1) c = ax.pcolor(df.index, np.arange(0, len(df.columns) + 1), df.T, cmap=cm.jet, vmin = -80, vmax = -20) ax.set_yticks(np.arange(len(df.columns))[::4]) ax.set_yticklabels(np.array(df.columns)[::4]) fig.colorbar(c, ax=ax)
こちらはオブジェクト指向インターフェースを使った書き方です。
上のpyplotインターフェースと違うところは、いったんset_yticksでY軸を0~バンド幅に設定した後で、set_yticklabelsを使用してラベルの値を設定しているというところです。
先ほどと同様にラベルは4個飛ばしにしていますが、いい感じの値を使用してください。
ラベルを飛ばさないとすべてのオクターブバンドがY軸に表示されてしまい、見た目がよろしくなかったです。
おまけ:matplotlibのグラフインターフェースについて
ネット上でmatplotlibの使い方を調べると、「plt.なんとか」と書く方法と「ax.なんとか」と書く方法が存在します。
これらの違いですが、「plt.なんとか」のほうはpyplotインターフェースと呼ばれており、最後に使ったグラフの設定を勝手に変更してくれます。
利用方法が簡単なため、グラフをさっと表示するには向いています。
ただし、細かい調整をするのには向いていないと感じます。
一方で「ax.なんとか」はオブジェクト指向インターフェースと呼ばれており、matplotlibのグラフの各要素のオブジェクトを自分で明示的に取得し、そのオブジェクトに任意の設定を行うことができます。
グラフ表示にはひと手間かかってしまうものの、細かい調整が可能となります。
コメント