Polarsのplotを理解する


Polars には `df.plot...` による可視化機能が存在します。データの前処理からスムーズにグラフ作成に繋げられ、データ確認に非常に便利です。

本記事では、そんな Polars の可視化機能の概要や使い方についてご紹介します。


# まずは使い方を理解する
## ３行で理解するpolars.plot
基本的な使い方はシンプルで、データフレームに対して `.plot` を続けることでグラフ作成できます。

```python
import polars as pl

# palmerpenguins のデータを利用
df = pl.read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/refs/heads/master/penguins.csv")

# 散布図の作成
df.plot.point(x="bill_length_mm", y="bill_depth_mm", color="species")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/84bf7894-2807-e96b-527f-8865dfaa5bef.png)


## 描写できるグラフ一覧
現時点で実装されているグラフはそこまで多くないです[^alt_mark_list]。

- `.plot.bar`
- `.plot.line`
- `.plot.point` （ `.plot.scatter` も同じ）

後述しますが、これらの組み合わせでヒストグラムなども作成できるため、これだけでもある程度は対応できる印象です。

[^alt_mark_list]: Altair側だとより多くのグラフ種類があります。https://altair-viz.github.io/user_guide/marks/index.html

## インストール
pip で入ります。Google Colabだとデフォルトで必要なものがインストールされているので、そのまま使えます。

```
pip install polars[plot]
```

既に Polars のみ導入している場合、 `altair>=5.4.0` をインストールすればOKです。

```
pip install altair
```

# plot機能の中身を理解する
実は Polars の plot機能は、Altair のグラフ作成を呼び出しているだけです。

バックエンドに使われている **Altair** は、日本での知名度はそこまで高くないものの、使い勝手が良い可視化ライブラリです。Altair についてはこの記事の後半「Altairを理解する」で説明します。


## なぜ Altair？
端的に言うと、Altair 側が Polars に対応しているからです。[この公式のブログ](https://pola.rs/posts/lightweight_plotting/)で紹介されていますが、その裏には Narwhals なるものが存在しています（こちらも後述の「Narwhalsを理解する」で簡単に解説します）。

という理由なので、将来的にバックエンドは変わる可能性は全然あります。

## hvplot
実は最初はバックエンドがhvplot でした。ver 1.6.0 以降 Altair になったのですが、以下のように記述すると hvplot も使えます。

```python
import hvplot.polars

df.hvplot.scatter(x="bill_length_mm", y="bill_depth_mm")
```

ちなみに hvplot は、複数のデータフレームライブラリから HoloView というラッパーを介してグラフを可視化するライブラリです。詳細は以下の記事などを参照ください。

- [hvPlot — hvPlot 0.11.2 documentation](https://hvplot.holoviz.org/)
- [【Python】hvPlotの使い方・やり方を解説 | 月見ブログ](https://tsukimitech.com/python_hvplot/)

なお、もちろん他の可視化ライブラリ（matplotlib, seaborn, plotlyなどなど）に Polars のデータフレームをインプットとして入れることはもちろん可能です。

## ドキュメント
ユーザーガイド

https://docs.pola.rs/user-guide/misc/visualization/

APIリファレンス

https://docs.pola.rs/api/python/stable/reference/dataframe/plot.html

Altair になった経緯に関する Blog

https://pola.rs/posts/lightweight_plotting/



# Altairを理解する
Altair は JavaScript のグラフ作成ライブラリである **Vega-Lite** に基づいて作られた Python ライブラリです。ドキュメントのタイトルに「A Grammar of Interactive Graphics」と書いているように、R の ggplot とかと似た書き味な気がします。Python だと **seaborn** (matplotlibではなく) や **plotly.express** (plotlyではなく) などと似た立ち位置です。


## Altair の基本概念

※説明は「- [Simple Charts: Core Concepts — Altair Tutorial](https://altair-viz.github.io/altair-tutorial/notebooks/02-Simple-Charts.html#encodings)」を参考にしています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/aa6d90b3-cf49-007c-e4d4-d77b3f16fe26.png)

- **Chart**: グラフそのものを Chart オブジェクトと言い、その重要な要素が Data, Mark, Encoding の３つ
- **Data**: 各行が観測値、各列が変数を表す「tidy」形式であることが推奨される
- **Mark**: 基本的なグラフィックの要素
- **Encoding**: DataのカラムをMarkの視覚的要素にマッピングさせる

Polars の `.plot` のなかだと以下で対応されます。
- Data: 呼びだしている DataFrame
- Mark: `.plot` に続けて記載（point, line, barのいずれか）
- Encoding: 引数としてカラムを指定

## Altairの便利機能など
### Layered & Multi-View Charts
複数のグラフを重ねたり並べたりできる。

Line＋Point＋Barを重ねる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/89c78c56-ec4c-4470-41b6-9a858542de8d.png" width="300" height="200">

横に並べる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/a5f6f8e7-c2fd-48f2-2517-e3801265cbfe.png" width="300" height="200">

ちなみにこんな感じでシンプルに書けます

```python
# 重ねる
fig1 + fig2

# 横に並べる
fig1 | fig2

# 縦に並べる
fig1 & fig2
```

- [Layered & Multi-View Charts — Vega-Altair 5.5.0 documentation](https://altair-viz.github.io/user_guide/compound_charts.html)

### Interactive Charts
操作性も柔軟に設定可能です。
これは実際に触ってもらうのが一番分かりやすいと思うので、当該のドキュメントをご覧ください。

https://altair-viz.github.io/user_guide/interactions/parameters.html

https://altair-viz.github.io/altair-tutorial/notebooks/06-Selections.html

https://idl.uw.edu/visualization-curriculum/altair_interaction.html

### Top-Level Chart Configuration
サイズや軸や凡例など、細かい調整はこのあたりにまとまってます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/9d7f26df-b21d-6269-e2c3-a60a06229281.png" width="500">

- https://altair-viz.github.io/user_guide/configuration.html
- https://altair-viz.github.io/user_guide/customization.html

## Altairに関する参考リンク
上記紹介したもの以外にもいろいろ柔軟に設定可能です。３つ目の日本語記事はかなり詳細に解説してくれており、参考になりそうです。

- [Vega-Altair: Declarative Visualization in Python — Vega-Altair 5.5.0 documentation](https://altair-viz.github.io/)
- [Introduction — Visualization Curriculum](https://idl.uw.edu/visualization-curriculum/intro.html)
- [【Python】データ可視化ライブラリAltairハンズオン【基礎編】 #データサイエンス - Qiita](https://qiita.com/keisuke-ota/items/9b51c4352f93bd755b15)



# Narwalsを理解する

上で述べたように、Polars の plot は Narwhals ライブラリが基盤になっています。

**Narwhals** は、pandas、Polars、cuDF などの異なるデータフレームライブラリ間の互換性を提供する軽量な Python ライブラリで、ライブラリ開発者がデータフレームに依存しないコードを記述することを支援します。

（なので私たちユーザーは Narwhals の存在を意識することなく、知らぬ間に恩恵を受ける類のものです。）

- [GitHub - narwhals-dev/narwhals: Lightweight and extensible compatibility layer between dataframe libraries!](https://github.com/narwhals-dev/narwhals?tab=readme-ov-file)
 - [Narwhals](https://narwhals-dev.github.io/narwhals/)
- [【Python】DataFrame系ライブラリ統一されてた #pandas - Qiita](https://qiita.com/Hanjin_Liu/items/4244f12dca87f24a0baa)


# 可視化スピードを検証する

Polars といえば Blazing Fast。ということで、ほかと比較してこの `df.plot` も高速かどうかを簡易的に検証してみます[^speed]。

比較したもの
- polars.plot
- seaborn (polars)
- plotly (polars)
- pandas.plot
- seaborn(pandas)
- plotly(pandas)

設定として、時間がかかってストレスに感じることが多い、行数の多いデータの散布図の可視化を行います。

[^speed]: 適当に測っただけで、全くもって正確な検証ではありません。結果は信用しないでください。

## 検証結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/78a2a5f1-ff6b-2499-9f5b-ae139d687bff.png)

そんなに polars の `.plot` が速いわけではないですね…

plotlyは内部的に一度 pandas に変換する処理で時間がかかってるとかでしょうか？


# Exampleで理解する
実際に使っていくうえで直面しそうなグラフを例として記載します。

詳細はここを見るのが良きです。

https://altair-viz.github.io/gallery/index.html

## histogram

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/24034ec8-7e9b-6cba-58dc-f0375193a09a.png)


```python
import polara as pl
import altair as alt

df = pl.read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/refs/heads/master/penguins.csv")

# 件数を縦軸にする（＝ヒストグラムとして `bar` を作成）
fig1 = df.plot.bar(x="bill_length_mm", y="count()")

# 横軸をBinで切る
fig2 = df.plot.bar(
    alt.X("bill_length_mm:Q").bin().title('くちばしの長さ'),
    y="count()"
)

# 横に並べる
fig1 | fig2
```

### サイズ変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665792/ac1a24c0-dbdf-5833-5648-7413e85d5f9d.png)


```python
df.plot.point(
    # ゼロを初期描写範囲に含まない
    x=alt.X("bill_length_mm", scale=alt.Scale(zero=False)),
    y=alt.Y("bill_depth_mm", scale=alt.Scale(zero=False)),
    color=alt.Color('body_mass_g:Q').bin(maxbins=5)
).properties(
    # Chart自体のサイズ
    width=600,
    height=400 
).configure_axis(
    # 軸のフォントサイズ
    labelFontSize=20,
    titleFontSize=20,
).configure_legend(
    # 凡例のフォントサイズ
    labelFontSize=20,
    titleFontSize=20,
)
```

...他の例も追記予定です

# 終わりに
実は今回この記事を書くにあたって初めて Altair をちゃんと触ったのですが、なかなか良さそうでした。デフォルトの描画サイズが小さくて好みではないものの、それを除くと快適に使えそうです。

もともと Pandas はデータ加工よりもデータ可視化ライブラリとして有用だと思っていたのですが、これや `df.style` による [GreatTables を用いた表の整形](https://docs.pola.rs/user-guide/misc/styling/)など機能が増えてきており、全て Polars で賄える状況になりつつある印象です。

ということで、みなさまも良い Polars ライフを！