Python可視化ライブラリAltairをMatplotlibやPlotly、Bokehと比較してみた

こんにちは!この記事を書いた理由は、大学院の授業でAltairを教えてもらい、その性能や他の可視化ライブラリとの違いを理解したかったからです。これまで主にMatplotlibPlotlyBokehといった他の可視化ライブラリを使用してきましたが、Altairとの違いやそれぞれの強み・弱みを明確に理解することで、プロジェクトに最適なツールを選択できるようになりたいと考えました。

本記事では、**同じ「棒グラフ」**を4つのライブラリでどのように作成するかを実例コードとともに紹介し、それぞれのメリット・デメリットを比較します。Pythonでの可視化手法を幅広く知りたい方や、Altairに興味を持った方の参考になれば幸いです。

目次

  1. Altairとは?
  2. 他のライブラリの概要
  3. 同じ可視化を4ライブラリで比較
  4. コード比較まとめ
  5. どれを選ぶべき?(ざっくり指針)
  6. まとめ

Altairとは?

Altair は、Vega-Lite をベースとした 宣言型 データ可視化ライブラリです。次のような特徴があります。

  • 簡潔な文法: mark_line()mark_bar(), encode() など、少ないコードでグラフの意図を記述しやすい
  • インタラクティブ性: ツールチップやズームなど、インタラクティブ機能の追加が手軽
  • 統計的可視化に強み: 散布図やヒートマップなど、変数間の関係を直感的に把握する可視化が得意

一方で、数万行を超える大規模データ ではブラウザ依存のためパフォーマンスが低下しやすい、また非常に細かなカスタマイズには Matplotlib ほど向いていないといったデメリットがあります。


他のライブラリの概要

Matplotlib

  • 特徴: Python 可視化の「定番」。歴史が長く、論文や学会用の図などアカデミック用途でも多数採用
  • 長所: 細部まで描画をコントロールできる
  • 短所: コードが冗長になりがちで、インタラクティブ機能が標準では弱い

Plotly

  • 特徴: Web 上での対話的な可視化や、大規模データを扱う際のパフォーマンスが比較的優秀
  • 長所: デフォルトでホバーやズームなど機能が豊富、ダッシュボード化もしやすい
  • 短所: オプションが多く、慣れないうちは複雑に感じる場合あり

Bokeh

  • 特徴: Webアプリケーションとの統合を意識したインタラクティブ可視化ライブラリ
  • 長所: JavaScript 拡張や、複雑なインタラクティブダッシュボード作成が得意
  • 短所: ColumnDataSource など独自の概念がやや複雑。初期設定も多め

同じ可視化を4ライブラリで比較

ここでは 同じ「棒グラフ」 を描画してみます。それぞれのライブラリでコードの書き方がどう違うのかを見比べてみてください。

サンプルデータの用意

まず、4 ライブラリ共通で用いるデータを用意します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import pandas as pd

# サンプルデータ
df = pd.DataFrame({
    'fruit': ['Apple', 'Apple', 'Banana', 'Banana', 'Orange', 'Orange'],
    'type': ['A', 'B', 'A', 'B', 'A', 'B'],
    'sales': [30, 45, 10, 25, 40, 35]
})

df

fruit    type    sales
Apple    A       30
Apple    B       45
Banana   A       10
Banana   B       25
Orange   A       40
Orange   B       35

今回の目的はfruit×type の売上 (sales) を棒グラフで表現することです

## Matplotlibでの実装

```python
import matplotlib.pyplot as plt
import numpy as np

fruits = df['fruit'].unique()
types = df['type'].unique()

x_indices = np.arange(len(fruits))
bar_width = 0.35

# Type A と Type B の sales を抽出
sales_A = df[df['type'] == 'A'].sort_values('fruit')['sales'].values
sales_B = df[df['type'] == 'B'].sort_values('fruit')['sales'].values

fig, ax = plt.subplots(figsize=(6, 4))

# Type A のバー
ax.bar(x_indices, sales_A, width=bar_width, label='Type A')
# Type B のバー(少し右にずらす)
ax.bar(x_indices + bar_width, sales_B, width=bar_width, label='Type B')

ax.set_xticks(x_indices + bar_width/2)
ax.set_xticklabels(fruits)

ax.set_title("Matplotlib Bar Chart")
ax.set_xlabel("Fruit")
ax.set_ylabel("Sales")
ax.legend()

plt.show()

Matplotlibのポイント

  • 自分で x 軸の位置を計算して並べる必要がある
  • 細部まで手動調整できるため、学術的に高精度の図を作るときに便利
  • インタラクティブ機能は標準状態では少なめ

Altairでの実装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import altair as alt

chart = alt.Chart(df).mark_bar().encode(
    x=alt.X('fruit:N', title='Fruit'),  # 名義データ
    y=alt.Y('sales:Q', title='Sales'),  # 数値データ
    color='type:N',                     # type を色分けに使う
    column='type:N'                     # typeごとに列で分割表示
).properties(
    title='Altair Bar Chart'
)

chart

Altairのポイント

  • 宣言型文法 により、少ないコードで可視化ができる
  • column=‘type:N’ のように、行や列に次元を割り当てて複合表示するのが簡単
  • 数万行を超えるデータではパフォーマンスに注意

Plotlyでの実装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import plotly.express as px

fig = px.bar(
    df,
    x='fruit',
    y='sales',
    color='type',
    barmode='group',    # 並行バー表示
    title='Plotly Bar Chart'
)
fig.show()

Plotlyのポイント

  • px.bar() に引数を渡すだけでシンプルにグラフが作れる
  • デフォルトでホバー機能やズーム機能などインタラクティブ性が高い
  • 大規模データにも比較的強い

Bokehでの実装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource
from bokeh.transform import dodge
from bokeh.io import output_notebook

output_notebook()

source = ColumnDataSource(df)

fruits = list(df['fruit'].unique())
p = figure(
    x_range=fruits,
    plot_height=300,
    title="Bokeh Bar Chart",
    toolbar_location=None
)

# Type A のバー
p.vbar(
    x=dodge('fruit', -0.15, range=p.x_range),
    top='sales',
    width=0.3,
    source=source[df['type'] == 'A'],
    color="blue",
    legend_label="Type A"
)

# Type B のバー
p.vbar(
    x=dodge('fruit', 0.15, range=p.x_range),
    top='sales',
    width=0.3,
    source=source[df['type'] == 'B'],
    color="orange",
    legend_label="Type B"
)

p.x_range.range_padding = 0.1
p.legend.location = "top_left"
p.xgrid.grid_line_color = None

show(p)

Bokehのポイント

  • Webアプリケーション統合 に向けて設計されている
  • ColumnDataSource と dodge による座標制御など、やや独特の書き方
  • JavaScript 拡張や高度なインタラクションを付与しやすい

コード比較まとめ

ライブラリ コードの特徴 メリット デメリット Matplotlib - 定番で資料豊富- 手動で座標を扱うなど自由度が高い - 学術利用などで精密な描画- 長年の実績 - 設定箇所が多くコードが冗長- インタラクティブ性が標準で弱い Altair - 宣言型で非常にコードが簡潔- encode() でデータ割り当て - わかりやすいシンタックス- レイヤー可視化も容易 - 大規模データだとパフォーマンス低下- 細部カスタマイズは苦手 Plotly - px.bar() などでシンプルに書けるが詳細設定も可能 - インタラクションが強力- 大規模データも割と軽い - オプションが豊富で慣れないと複雑- Altair ほどシンプルではない Bokeh - Webアプリ連携を重視- ColumnDataSource など独特の概念 - 高度なWeb拡張とインタラクティブ機能- ダッシュボード化も容易 - 初期設定が手間- Altair ほどのシンプルさはない

どれを選ぶべき?(ざっくり指針)

  • Altair
    • 宣言型文法でスピーディにグラフを作りたい
    • 小~中規模データに最適
    • 統計的可視化や多次元可視化が多いプロジェクト
  • Matplotlib
    • 歴史が長くドキュメントが豊富
    • 学術用途や論文・学会用など厳密かつ細かい調整が必要
    • インタラクティブ性より高精度な描画が重要
  • Plotly
    • インタラクティブな可視化と大規模データに強い
    • ダッシュボードや Web 共有を考えている
    • 直感的な操作を重視したい
  • Bokeh
    • Webアプリケーション組み込みや JavaScript 拡張が必要
    • Flask / Django などで高度なダッシュボードを自作
    • 初期設定はやや複雑だが、柔軟性が高い

まとめ

大学院の授業で Altair を教わったのをきっかけに、従来使っていた Matplotlib や Plotly などと比較しながらまとめてみました。

同じ「棒グラフ」を描くだけでも、ライブラリごとに

  • コードの長さ
  • インタラクティブ性・カスタマイズ性
  • 大規模データへの対応 などが異なることがわかります。
  • Altair は宣言型でわかりやすく、インタラクティブ性を簡単に導入可能
  • Matplotlib は定番であり、カスタマイズの幅が最も広い
  • Plotly はインタラクション+大規模データ、ダッシュボード化に強い
  • Bokeh は Web アプリとの統合や JavaScript 拡張が必要な場面に最適

どれか一つを「絶対に使う」と決めるよりも、プロジェクトの規模やニーズ、データの性質にあわせて最適なツールを選ぶのが賢い戦略です。小~中規模のデータ探索には Altair、学術的な厳密描画には Matplotlib、インタラクティブダッシュボードや大規模データ解析には Plotly や Bokeh など、使い分けを意識してみてください。