静かなる名辞

pythonとプログラミングのこと

2019/03/22:TechAcademyがteratailの質問・回答を盗用していた件
2019/03/26:TechAcademy盗用事件 公式発表と深まる疑念


【python】seabornで折れ線グラフを信頼区間付きで描く

はじめに

 信頼区間というとなんとなく棒グラフにつけるものという印象がありますが、折れ線グラフでも計算すること自体はたやすくて、しかもけっこうかっこいいグラフになります。

 大抵は別に無くても良いのですが、たまに信頼区間が出ていると便利なときがあります(有意な差があるかどうかを視覚的に示せます)。

 seabornでできるのでやってみます。

seaborn.lineplot — seaborn 0.9.0 documentation

 

DataFrameを入力して使う

 リファレンスではこの方法が推されています。DataFrameがあるのであれば簡単にできます。

 公式の例をパクってきたような感じの実行例を以下に示します。

import seaborn as sns
import matplotlib.pyplot as plt

fmri = sns.load_dataset("fmri")
print(fmri.head())  # どんなデータなのか見ておく
""" =>
  subject  timepoint event    region    signal
0     s13         18  stim  parietal -0.017552
1      s5         14  stim  parietal -0.080883
2     s12         18  stim  parietal -0.081033
3     s11         18  stim  parietal -0.046134
4     s10         18  stim  parietal -0.037970
"""

sns.lineplot(x="timepoint", y="signal", data=fmri)
plt.savefig("result.png")

result.png
result.png

 何をやっているのかと言うと、timepointで集計してsignalの信頼区間(デフォルトは95%)を計算しています。たったこれだけの指定でこれだけのことをしてくれるので、便利なものです。

 裏を返せば、同じx軸の値に対して対応するy軸の値が複数ないと信頼区間は出ません(当たり前のことですが)。

面倒くさいのでただの配列で計算できるようにする

 seabornのリファレンスではDataFrameを入力にして使う方法がやたら推されていますが、私はpandasは扱うのが面倒くさいので、numpy配列ですませたいと思うタイプの人間です。

 その場合のやり方ですが、まず上に挙げた例は、以下のように書いても同じ結果が得られます。

sns.lineplot(x=fmri["timepoint"], y=fmri["signal"])

 性質はよくわかったので、numpyで作ったサイン波でやってみます。

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

x = np.repeat(np.linspace(0, 10, 20), 20)
# たとえばnp.repeat(np.arange(5), 2)は
# array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4])になる性質があります
y = np.sin(x) + np.random.normal(size=x.shape)

sns.lineplot(x=x, y=y)
plt.savefig("result.png")

result.png
result.png

 微妙な使い勝手ですが(どちらかといえば外側でgroupbyした結果で渡したいんだけどな、とか)、使えるには使えます。

 ちなみに上のグラフを見て気づいた方もいるかと思いますが、基本的にはxの値でグルーピングしたあとそれぞれのxに対応する信頼区間を計算しているだけのようです。点の信頼区間同士も線形に折れ線で繋がれます(ので、点と点の間で妥当なことになっている保障はないと考えた方が無難です)。

まとめ

 折れ線グラフで信頼区間を議論することはあまりないかもしれませんが、それでもたま~に便利なときがあるので、覚えておいて損はないです。