pythonでデータを可視化したいならseabornを使おう！

pythonでデータを可視化するのにmatplotlibを使う人は多いと思いますが、seabornというmatplotlibのラッパーが素晴らしく便利です。

# インストール

まずはseabornをインストールします。pipもしくはcondaでインストールできます。

```
pip install seaborn
````

```
conda install seaborn
```

# 前準備

seabornはnumpy, matplotlib, pandasに依存しているので、同時にimportします。

```py
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

%matplotlib inline
```

サンプルデータとして、titanic,tips,irisのデータセットを使います。

```py
titanic = sns.load_dataset("titanic")
tips = sns.load_dataset("tips")
iris = sns.load_dataset("iris")
```

# 変数分布を知る

とりあえずある変数の分布はどうなっているのだろう？と可視化することはよくあります。seabornだと、matplotlib以上の情報を簡単に与えてくれるため、得られるインサイトの費用対効果がとても大きいです。早速見てみましょう。

## 1変数の場合（distplot）

まず、データを用意します。標準正規分布に従う乱数を100件用意しておきます。

```py
x = np.random.normal(size=100)
```

distplot()関数を使うと、ヒストグラムとKDEが同時に表示されます。これだけでも結構便利です。ヒストグラムだけ表示したり、より細かい分布をみたり等の調節もできます。

```py
sns.distplot(x)
```

<img width="387" alt="Screen Shot 2018-03-19 at 16.24.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/348435f7-72ce-e72f-a68f-a1dead2fe3d2.png">

## 2変数の場合（jointplot）

次に、変数をxとyの2つに増やしてみます。pandasのDataFrameを用います。

```py
mean, cov = [0, 1], [(1, .5), (.5, 1)]
data = np.random.multivariate_normal(mean, cov, 200)
df = pd.DataFrame(data, columns=["x", "y"])
df.head()
```
こんなデータです。

```
	x	y
0	1.512856	2.527512
1	0.311464	2.143966
2	0.774056	1.870894
3	-0.995346	-0.371048
4	0.756758	2.866903
```

2変数の分布を可視化するのには、jointplot()関数を用います。x軸・y軸・dataを指定してあげればOKです。2変数の散布図・各変数のヒストグラムが同時に見られます。素晴らしすぎる。

```py
sns.jointplot(x="x", y="y", data=df)
```
<img width="440" alt="Screen Shot 2018-03-19 at 16.25.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/24c74b24-99b9-d70f-6273-f10d1acf90e9.png">

# カテゴリ情報を知る

データを眺めるとき、「カテゴリごとに変数の分布がどうなっているか」などカテゴリごとに変数の特徴を押さえたいケースがよくあります。seabornはカテゴリに対する可視化にもうってつけです。

## カテゴリごとのデータの分布を見る

曜日ごとにチップとして支払われている額に傾向があるのか、男性・女性では、喫煙かどうかは影響するの？　はい、`stripplot()`関数を使えば一発で可視化できます。

```py
sns.stripplot(x="day", y="total_bill", data=tips)
```

<img width="411" alt="Screen Shot 2018-03-19 at 16.27.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/79efc077-ffdc-52bf-2541-9c7eb7acac8c.png">

swarmplot()関数にすると、データの分布が重ならないように調節してくれます。

```py
sns.swarmplot(x="day", y="total_bill", data=tips)
```

<img width="404" alt="Screen Shot 2018-03-19 at 16.28.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/b84c014f-0948-afa3-6453-1bf2b0288302.png">

hueという引数に新たな変数を設定することで、新たな変数を加えることができます。性別という情報も加えて可視化してみます。どこまでやってくれるんだseabornは。

```py
sns.swarmplot(x="day", y="total_bill", hue="sex", data=tips)
```
<img width="403" alt="Screen Shot 2018-03-19 at 16.28.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/7c5e30cb-b956-46c7-781a-0d1b95fe55e0.png">

## カテゴリごとのデータの分散を見る

箱ひげ図を用いてデータを可視化することで、上の散布図で見るよりも正確にデータを捉えることができます。`boxplot()`関数を用います。

```py
sns.boxplot(x="day", y="total_bill", data=tips)
```

<img width="402" alt="Screen Shot 2018-03-19 at 16.29.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/dffcb896-075b-7bb4-1950-db68b9080e0d.png">

## 統計的にデータを推定する

`barplot()`関数を用いて、棒グラフを書くことができます。以下ではtitanicのデータセットを使います。性別・客室の階級と生存有無にどのような関係があるかを一発で可視化しています。

```py
sns.barplot(x="sex", y="survived", hue="class", data=titanic)
```
<img width="399" alt="Screen Shot 2018-03-19 at 16.30.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/44e8c37e-9720-6e9f-8a1a-1fdb50829ebf.png">

poitplot()関数を用いることで、上のデータをシンプルに置き換えることができます。

```py
sns.pointplot(x="sex", y="survived", hue="class", data=titanic)
```

<img width="409" alt="Screen Shot 2018-03-19 at 16.30.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/3ab6de98-ac0d-374a-efdb-26314e3b48af.png">

# 線形回帰モデルを知る

## 線形回帰直線を描く

seabornを使えば、分布図の上に線形回帰直線を引くのも一瞬でできます。`regplot()`関数を用います。

```py
sns.regplot(x="total_bill", y="tip", data=tips)
```

<img width="405" alt="Screen Shot 2018-03-19 at 16.42.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/d013161f-d429-f7d5-8fce-a7ab8966bbc8.png">


同じことは、lmplot()関数でもできます。両者の違いは、regplot()は、データをpandas.Seriesやpandas.DataFrameなどどのような形で渡しても良い一方で、lmplot()は、必ずxとyを指定しなければならない点です。

```py
sns.lmplot(x="total_bill", y="tip", data=tips)
```

<img width="382" alt="Screen Shot 2018-03-19 at 16.42.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/2542cc06-14bb-b8f9-bf12-e6c44050d845.png">


上と同じように、hueを与えれば変数を増やして可視化することができます。

```py
sns.lmplot(x="total_bill", y="tip", hue="smoker", data=tips)
```

<img width="430" alt="Screen Shot 2018-03-19 at 16.42.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/30a89dea-fcf2-b1cb-3667-7da0e1b70a1e.png">


# 巨大なデータセットから効率よくインサイトを得る

とりあえずデータが手元にあるけど、何もわかっていない。どこから手をつけたらいいのやら、、、となった場面でもseabornが活躍します。irisのデータセットを用います。`pairplot()`関数を用いることで一気に関係性を可視化できます。これは、データを触りはじめる一番最初にやりたいことです。

```py
sns.pairplot(iris, hue="species", size=2.5)
```

<img width="724" alt="Screen Shot 2018-03-19 at 16.43.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/108729/103695f7-0458-508c-e219-fc4ae11232df.png">


# まとめ

seabornを使ってデータを可視化してみました。今までmatplotlibを使ってデータを可視化していた自分としては、素晴らしいの一言につきます。データを触っている以上、それを可視化してインサイトを得ることは基本中の基本なので、これだけ便利にかつ高性能に可視化をしてくれるツールは使わなければなりません。

参考： [Seaborn Documentation](https://seaborn.pydata.org/index.html)

ブログも書いているのでぜひ！

[筋肉をこよなく愛するエンジニアのブログ](https://muscle-programmer.hatenablog.com/entry/2018/03/19/164815/)