seaborn の jointplot を patchworklib で並べてそれぞれにタイトルをつける方法

# 記事の更新について

- 2023-02-24  記事を公開
- 2023-02-25  Patchworklib の作者の @ponnhide さんの[コメント](
https://qiita.com/yuifu/items/905bff9ae4dee556adc0#comment-82c4f078b3566a841395)をいただき、記事を修正
    - 変更点
        - 「コピペで試せるコード例」を更新（場合を分けました）
        - `set_suptitle()` を使う方法の説明を追記
        - [APIドキュメント](https://github.com/ponnhide/patchworklib/blob/main/API.md)へのリンクを追加

# この記事について

- seaborn の jointplot を patchworklib で並べてそれぞれにタイトルをつける方法を書いています
    - 下の図の "This is g1!"、 "This is g２!" のところがタイトル
        - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18504/705bdebe-2943-afba-c408-68c8d157ba57.png)

# コピペで試せるコード例 （各subplot自体の中央にタイトルを配置する場合）

- こんな図ができます：
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18504/7c5a747d-3b29-2616-342e-936a5c7f132e.png)
- キモ
    - `patchworklib.Bricks` クラスの `set_suptitle()` を使用することで、各プロットに suptitile ([図の上部のタイトルのこと](https://stackoverflow.com/questions/44308195/matplotlib-figure-suptitle-what-does-sup-stand-for)) を表示します

```python
import seaborn as sns
import patchworklib as pw 
import matplotlib.pyplot as plt

sns.set_theme()
pw.overwrite_axisgrid() 

# A JointGrid
titanic = sns.load_dataset("titanic")
g1 = sns.jointplot(data=titanic, x="age", y="fare")
g1 = pw.load_seaborngrid(g1, label="g1")
g1.set_suptitle("This is g1!", fontsize = 24)

# A JointGrid
iris = sns.load_dataset("iris")
g2 = sns.jointplot(data=iris, x="sepal_width", y="petal_length",
                   kind="kde", space=0, color="g")
g2 = pw.load_seaborngrid(g2, label="g2")
g2.set_suptitle("This is g2!", fontsize = 24)

# Horizontal arrangement
(g1|g2).savefig()
```

# コピペで試せるコード例 （subplotの中のjointplotの中の ax_marg_x の上部にタイトルを配置する場合）

- こんな図ができます：
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18504/48551e7b-7322-a8c4-0bda-911411fe9c03.png)
- キモ
    - `JointGrid` クラスオブジェクトの `ax_marg_x` に対して `set_title()` を使用するとことで、ax_marg_x の上部にタイトルを配置します
    - 下のコードだと `pw.load_seaborngrid()` によって、`JointGrid` クラスオブジェクトだった `g1` (`g2`) が `patchworklib.Bricks` クラスオブジェクトに上書きされます。そのため、`pw.load_seaborngrid()` を呼び出す前に、`.ax_marg_x.set_title()` を実行しています。
        - なので、あまり綺麗なコードではありません。

```python
import seaborn as sns
import patchworklib as pw 
import matplotlib.pyplot as plt

sns.set_theme()
pw.overwrite_axisgrid() 

# A JointGrid
titanic = sns.load_dataset("titanic")
g1 = sns.jointplot(data=titanic, x="age", y="fare")
g1.ax_marg_x.set_title("This is g1!", fontsize = 24)
g1 = pw.load_seaborngrid(g1, label="g1")


# A JointGrid
iris = sns.load_dataset("iris")
g2 = sns.jointplot(data=iris, x="sepal_width", y="petal_length",
                   kind="kde", space=0, color="g")
g2.ax_marg_x.set_title("This is g2!", fontsize = 24)
g2 = pw.load_seaborngrid(g2, label="g2")

# Horizontal arrangement
(g1|g2).savefig()
```




# 考えたこと

## **[2023-02-25  追記]**
- **Patchworklib の作者の @ponnhide さんの[コメント](
https://qiita.com/yuifu/items/905bff9ae4dee556adc0#comment-82c4f078b3566a841395)をいただき、もっと楽な方法＝`set_suptitle()` を使うことで目的が達成できました。**
- [Patchworklib の APIドキュメント](https://github.com/ponnhide/patchworklib/blob/main/API.md)にきちんと説明がありました。


## なぜこういうコードにしたか

「コピペで試せるコード例 （subplotの中のjointplotの中の ax_marg_x の上部にタイトルを配置する場合）」の場合：

- sns.jointplot は JointGrid class object を返します
- JointGrid の中で subplot をすでに作ってしまっています
    - https://github.com/mwaskom/seaborn/blob/master/seaborn/axisgrid.py#L1691-L1695
- class JointGrid は ax_joint, ax_marg_x, ax_marg_y という属性を持ちます。これらの属性は matplotlib.axes._subplots.AxesSubplot class object です。
    - https://github.com/mwaskom/seaborn/blob/master/seaborn/axisgrid.py#L1694 
- ax_joint, ax_marg_x, ax_marg_y のいずれかで　`set_title()` とすると、目的が達成できると思いました。実際に試し、ax_marg_x について `g1.ax_marg_x.set_title()` のようにすることで、タイトルをつけることができました。



## うまくいかなかったこと


- `suptitle`　を使う方法
    - https://stackoverflow.com/questions/60358228/how-to-set-title-on-seaborn-jointplot で紹介されていた方法
    - seaborn の　jointplot　を普通に使った場合は動きました
    - patchworklib で並べるコードにおいて試した結果、それぞれの図の上の位置にはタイトルが配置されませんでした
- patchworklib の `Brick` を利用する方法
    - https://zenn.dev/ponnhide/articles/40ac7dbe0aa4ab や　https://qiita.com/ponnhide/items/a261defb0203561bacf1 で紹介されていた方法
    - `ax1.set_title("ax1")` などとしてそれぞれのサブプロットに相当するオブジェクトに対して　`set_title()` でタイトルを設定する方法
    - seaborn の　jointplotではないプロットで試した場合は動きました
    - リンク先の記事のプロットを　seaborn の jointplot にした際にはうまくいきませんでした（空のプロットが表示されました）

# 参考

- patchworklib の公式
    - GitHub https://github.com/ponnhide/patchworklib
    - **APIドキュメント https://github.com/ponnhide/patchworklib/blob/main/API.md**
        - 詳しく説明されている
    - チュートリアル　https://colab.research.google.com/drive/1NfjyuKP9nqAM0hanvRHQP-kD1gbmP9Qz?usp=sharing#scrollTo=tZMlOe4lmGnx
    - https://github.com/mwaskom/seaborn/blob/master/seaborn/axisgrid.py
        - JointGrid の属性を調べるのに参照した
- https://stackoverflow.com/questions/35042255/how-to-plot-multiple-seaborn-jointplot-in-subplot
    -  patchworklib　の作者のコメントがあり、コード例のために参照した
- https://zenn.dev/ponnhide/articles/40ac7dbe0aa4ab
- https://qiita.com/ponnhide/items/a261defb0203561bacf1
- https://stackoverflow.com/questions/60358228/how-to-set-title-on-seaborn-jointplot