データサイエンス

Pythonの可視化パッケージ Seaborn の Lineplot の凡例でハマったこと

What is Seaborn?

Pythonの可視化パッケージにはいくつかありますが、そのうちの一つに Seaborn があります。
代表的なパッケージとしては以下があります。

それぞれにユニークな特徴がありますが、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データの構造に関する資料は以下のペーパーが気に入ってます。

Lineplot でハマった点

本題ですが、あるIoTデバイスの加速度データを周波数解析し、各周波数帯ごとのスペクトルパワーを可視化した際に、
その凡例が正しく表示されない挙動でハマりました。

前提条件は以下です。

  • Seaborn==0.9.0
  • 入力データフレーム (df_filter_bank)

f:id:gri-blog:20200123195817p:plain
(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 で描画するという単純なものです。
結果は以下のようになりました。

f:id:gri-blog:20200123200454p:plain

Vizの凡例(legend)に注目してください。プロットする波長は4つの組合せ(2, 4, 8, 16 時間)のはずなのに、
結果はなぜか(0, 5, 10, 15, 20)となっています。値が違うどころか、個数すら違います。

hue に指定したデータ型がNumeric が原因なのではと思い、文字列型にcastしたところ、以下のエラーが。。。

AttributeError: 'str' object has no attribute 'view'

解決した方法

以下のGithubのIssueに情報がありました。

詳細は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()
f:id:gri-blog:20200123212657p:plain

さいごに

Lineplot をつくる際には hue に数値型データを利用したいことは結構あると思います。Seaborn を上手く改修できるのが一番ですが、この記事ではちゃちゃっと改修するための方法を紹介しました。