Pythonでggplot2のようなグラフを描く： plotnineの使い方


R言語で可視化といったらggplot2でしょうか？では、Pythonで同じようにいい感じの可視化を行いたい場合何を使えばいいでしょうか。そのひとつの選択肢として挙げられるのが、plotnineというパッケージです。plotnineを使うことで、ggplot2とほとんど同じようにしてデータの可視化をすることができます。以下では、plotnineを使った基本的なプロット方法を紹介します。


### 環境準備

plotnineはpipでインストールできます。

```bash
pip install plotnine
```

本記事の内容に必要なインポートは以下のように行います。

```python
from plotnine import ggplot, aes, geom_point, geom_line, geom_bar, geom_smooth, labs, theme_minimal, facet_wrap, scale_color_brewer, stat_summary, position_jitter
import pandas as pd
import numpy as np
```

plotnine.dataモジュールにはmpgというサンプルデータセットが用意されています。

```python
from plotnine.data import mpg
mpg.head()
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176360/70d7c10a-353d-08bf-ef7a-bf8aaecb0c57.png" width=75%>

### 基本的な概念

plotnineではggplot()関数で「プロットオブジェクト」を生成し、その上に+演算子を用いてaes()、geom_XXXX()、theme()などの要素を追加していきます。
- ggplotオブジェクト: データと見せ方のマッピングをし、空の枠を準備する
- aes(): 軸（x, y）や色、形、サイズなどとデータを対応付ける
- geom_*: 散布図(geom_point)、折れ線(geom_line)、棒グラフ(geom_bar)など、実際のグラフ要素
- theme, facet_XXX: 外観の調整やデータ分割表示など

### 散布図の例

mpgデータセットを使い、車のエンジン排気量 displ と高速燃費 hwy の関係を散布図で可視化してみます。Rのggplot2だと`x=displ`などと指定しますが、pythonなのでここでは`x='displ'`として指定する必要があります。

```python
(
    ggplot(mpg, aes(x='displ', y='hwy')) 
    + geom_point()
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176360/99b86576-0938-56bd-e521-dacc846cf1dc.png" width=75%>

### 軸ラベルやタイトルの付与

labs()を使うと、タイトルや軸ラベルを付けられます。
```python
(
    ggplot(mpg, aes('displ', 'hwy'))
    + geom_point()
    + labs(title='Displacement vs Highway MPG', x='Engine Displacement (L)', y='Highway MPG')
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176360/d13d8552-3212-016b-23b0-3bb303074483.png" width=75%>

### 色分け

aes()内でcolor=にカテゴリ変数を割り当てることで、グループ別に色分けができます。
```python
(
    ggplot(mpg, aes('displ', 'hwy', color='class'))
    + geom_point()
    + labs(title='Displacement vs Highway MPG by Vehicle Class')
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176360/c0fe469e-3981-e01f-a73a-dcba58603b94.png" width=75%>

### テーマの変更

theme_*()関数で全体の見た目を変更できます。たとえばtheme_minimal()を使うとシンプルなデザインに。またscale_color_brewer()でカラーパレットを変更可能です。他にも様々な[テーマ](https://plotnine.org/reference/#themes:~:text=of%20each%20other-,Themes,-Themes%20control%20the)が用意されています。
```python
(
    ggplot(mpg, aes('displ', 'hwy', color='class'))
    + geom_point(size=3)
    + scale_color_brewer(type='qual', palette='Set1')
    + theme_minimal()
    + labs(title='Displacement vs Highway MPG (Minimal Theme)')
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176360/27a33daa-a964-a5cc-3eb2-d566c0db5796.png" width=75%>



### 分割表示

facet_wrap()で、カテゴリによって分割表示できます。
```python
(
    ggplot(mpg, aes('displ', 'hwy'))
    + geom_point()
    + facet_wrap('~class')
    + labs(title='Displacement vs Highway MPG by Class')
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176360/a922c659-f8da-b5be-7b58-6f657b45fbef.png" width=75%>

### プロットの重ね合わせ

複数のgeomのプロットを重ね合わせることが可能です。散布図の上に回帰直線を引くにはgeom_smooth()を追加します。

```python
(
    ggplot(mpg, aes('displ', 'hwy'))
    + geom_point(alpha=0.7)
    + geom_smooth(method='lm', color='red')
    + labs(title='Displacement vs Highway MPG with Regression Line')
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176360/3fef7966-b4a7-1992-c6a1-548054064c5e.png" width=75%>

これを応用して、ヒストグラムで平均を示しつつ、元データを重ねてプロットすることも可能です。
```python
(
    ggplot(data=mpg, mapping=aes(x='class', y='cty'))
    + stat_summary(geom='bar', fun_y=np.mean)
    + geom_point(mapping=aes(colour='class'), position=position_jitter(width=0.2, height=0), show_legend=False)
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176360/a94823bf-8222-55df-acca-460619fd2129.png" width=75%>


### まとめ
plotnineは、Pythonでggplot2ライクな記法を使いたい人にとって非常に有用なライブラリです。ベースの枠に+で要素を追加する直感的なスタイルは学習コストが低く、綺麗なグラフを簡単に生成できます。Rでggplot2を使っていた方も、Pythonでいい感じのデータの可視化を求める方も、ぜひplotnineを試してみてください。