DATA-SCIENCE
Pythonの可視化パッケージ Seaborn の Lineplot の凡例でハマったこと
What is Seaborn?
Pythonの可視化パッケージにはいくつかありますが、そのうちの一つに Seaborn があります。
代表的なパッケージとしては以下があります。
■Matplotlib: Matplotlib: Python plotting — Matplotlib 3.1.2 documentation
■Seaborn: seaborn: statistical data visualization — seaborn 0.9.0 documentation
■Dash (Plotly): Modern Analytic Apps for the Enterprise – Plotly
■Bokeh: <no title> — Bokeh 1.4.0 documentation
それぞれにユニークな特徴がありますが、Seaborn は 比較的に低級なパッケージである Matplotlib のラッパーになっていて、簡単にキレイなVizをつくれるというのが嬉しい特徴です。
また、最近のパッケージにはほとんど導入されていると思いますが、列指向のDataFrameを前提に作られています。BIツールのTableauも列指向のデータが前提ですね。Seaborn の ドキュメントには列指向データを以下のよう簡潔で分かりやすく表現しています。
(seaborn.lineplot の API reference より抜粋)
Parameters:
data : DataFrame
Tidy (“long-form”) dataframe where each column is a variable and each row is an observation.
データサイエンティストは Tidy なデータは大好物ですが、Messy なデータはちょっと嫌煙する方も多いのではないでしょうか。
ちなみにTidyデータの構造に関する資料は以下のペーパーをご参照いただくと分かり易いと思います。
https://vita.had.co.nz/papers/tidy-data.pdf
Lineplot でハマった点
あるIoTデバイスの加速度データを周波数解析し、各周波数帯ごとのスペクトルパワーを可視化した際に、その凡例が正しく表示されない挙動でハマりました。前提条件は以下です。
- Seaborn==0.9.0
- 入力データフレーム (df_filter_bank)
(sampling_at: 時刻, Period: 波長(周波数の逆数で、単位はhour), PSD: スペクトルパワー)
上記条件下で以下のコードを実行しました。
df_plot = df_filter_bank.loc[df_filter_bank['Period'].isin([2.0, 4.0, 8.0, 16.0])]
fig, ax = plt.subplots(figsize=(20, 8))
sns.lineplot(data=df_plot,
x=df_plot.index,
y='PSD',
hue='Period',
ax=ax)
fig.show()
上記コードを補足すると、波長が2, 4, 8, 16 時間のデータを抽出し、それらを個別にlineplot で描画するという単純なものです。
結果は以下のようになりました。
Vizの凡例(legend)に注目してください。プロットする波長は4つの組合せ(2, 4, 8, 16 時間)のはずなのに、結果はなぜか(0, 5, 10, 15, 20)となっています。値が違うどころか、個数すら違います。
hue に指定したデータ型がNumeric が原因なのではと思い、文字列型にcastしたところ、以下のエラーが…
AttributeError: 'str' object has no attribute 'view'
解決した方法
以下のGithubのIssueに情報がありました。
github.com
詳細はIssueを読んで頂ければ分かると思いますが、数値型データをhueとして使う場合には、一旦Tex形式の文字列にするという割とトリッキーな方法が紹介されてました。Matplotlib にはTex形式で数式記述ができる機能が公開されていて、それを利用しているんですね。
Writing mathematical expressions — Matplotlib 3.1.2 documentation
実際、実行コードを以下のようにすると正しい挙動になりました。
df_plot = df_filter_bank.loc[df_filter_bank['Period'].isin([2.0, 4.0, 8.0, 16.0])]
# 以下を追加
df_plot['Period'] = ["$%s$" % x for x in df_plot['Period']]
fig, ax = plt.subplots(figsize=(20, 8))
sns.lineplot(data=df_plot,
x=df_plot.index,
y='PSD',
hue='Period',
ax=ax)
fig.show()
さいごに
Lineplot をつくる際には hue に数値型データを利用したいことは結構あると思います。Seaborn を上手く改修できるのが一番ですが、この記事では手早く改修するための方法をご紹介しました。皆さんもSeabornを活用される際に、参考にしてください。
この記事をシェアする