Altairメモ
Altair
新興の可視化ライブラリ。
簡単に書きやすいらしい。
Vega
を使うから Altair
(アルタイル) らしい。
インストール
https://altair-viz.github.io/getting_started/installation.html
JupyterLab、Jupyter Notebook、Google Colabそれぞれでインストール方法が異なる。
Jupyter Notebook
$ pip install -U altair vega_datasets notebook vega
動作確認
import altair as alt
from vega_datasets import data
# for the notebook only (not for JupyterLab) run this command once per session
alt.renderers.enable('notebook')
iris = data.iris()
alt.Chart(iris).mark_point().encode(
x='petalLength',
y='petalWidth',
color='species'
)
左の図は、上のコードの出力結果。
なんと画像セーブメニューまで標準でついている。
チュートリアル
Altairのデータは pandas DataFrame を使う。
import pandas as pd
data = pd.DataFrame({'a': list('CCCDDDEEE'),
'b': [2, 7, 4, 1, 2, 6, 8, 4, 7]})
最も基本的なオブジェクトは Chart
である。
import altair as alt
chart = alt.Chart(data)
この Chart
に操作指示を出していくことになる。
エンコーディングとマーキング
データを可視化するには mark
属性を使う。この属性にアクセスするには Chart.mark_*
を使う。
alt.Chart(data).mark_point()
これは、1行ごとに1つの点をプロットしている。しかしポジションを指示していない。
点を分割描画するには encoding channel あるいは単に channel を使う。この例では、変数 a
を x
チャネルにエンコードしている。 x
チャネルはx軸を表す。
alt.Chart(data).mark_point().encode(
x='a',
)
チャネルには x
y
color
shape
size
などがある。
Altairはチャネルに渡すデータの型を自動で見てくれる。以下の例では、 b
が数値型だと自動で判別している。
alt.Chart(data).mark_point().encode(
x='a',
y='b'
)
データ変換: 集約
Altairはビルトインの集約文法を持っている。
alt.Chart(data).mark_point().encode(
x='a',
y='average(b)'
)
集約された値に対しては普通散布図ではなく棒グラフを使う。ここで、 mark_point()
を mark_bar()
に変えてみる。
alt.Chart(data).mark_bar().encode(
x='a',
y='average(b)'
)
縦軸でなくて、横軸にしてみる。 x
と y
を逆にしてみる。
alt.Chart(data).mark_bar().encode(
x='average(b)',
y='a'
)
to_json()
を使ったVega-Liteへのエクスポート
Vega-Lite使わないので省略
チャート編集の基本操作いくつか
バーの色を変える
Chart.mark_*
のcolorオプションを変更する。
alt.Chart(data).mark_bar(color="firebrick").encode(
x='average(b)',
y='a'
)
軸のタイトルをつける
x
チャネルではなく alt.X
を使う。
alt.Chart(data).mark_bar().encode(
alt.Y('a', title='category'),
alt.X('average(b)', title='avg(b) by category')
)
チャートを出力する
HTMLに出力する
chart = alt.Chart(data).mark_bar().encode(
x='a',
y='average(b)',
)
chart.save('chart.html')
動作環境
PyCharm + Jupyter notebook
Frequently Asked Questions - Altair 3.2.0 documentation
一応ここに方法っぽいものが書いてあるが、動かすとブラウザを起動してそこに結果を表示するというとんでもないシロモノだった。
おとなしく Jupyter notebook 起動した方がいい。
Chart
プロパティ
altair.Chart - Altair 3.2.0 documentation
チャートトップレベルのプロパティを指定できる。
# Base chart for data tables
ranked_text = alt.Chart(df).mark_text().encode(
y=alt.Y('row_number:O',axis=None)
).transform_window(
row_number='row_number()'
).transform_filter(
brush
).transform_window(
rank='rank(row_number)'
).transform_filter(
alt.datum.rank<50
)
# Data Tables
threshold = ranked_text.encode(text='threshold:N').properties(title='Threshold')
precision = ranked_text.encode(text='precision:N').properties(title='Precision')
recall = ranked_text.encode(text='recall:N').properties(title='Recall')
text = alt.hconcat(threshold, precision, recall) # Combine data tables
Encoding
チャネルオプション
Encodings - Altair 3.2.0 documentation
color
色を指定する
色そのものを指定するのではなく、色を指定するために参照するデータを与える。
alt.Chart(cars).mark_point().encode(
x='Acceleration:Q',
y='Miles_per_Gallon:Q',
color='Origin:N'
)
この例では、 Origin
という N
nominal data を色分けの参照データとしている。
sort
データをソートする
ソートのデフォルトは昇順(ascending)。
alt.Chart(iris).mark_text().encode(
y=alt.Y('petalWidth', axis=None), text='petalWidth'
)
sort="descending"
を設定することで降順にソートできる。
alt.Chart(iris).mark_text().encode(
y=alt.Y('petalWidth', axis=None, sort="descending"), text='petalWidth'
)
インタラクティブなチャートの作成
Selection
Bindings, Selections, Conditions: Making Charts Interactive - Altair 3.2.0 documentation
Selection
は、マウスを使ったインタラクティブな選択を行うときに使う。
Interval
brush = alt.selection(type='interval')
このIntervalだけでは単に画面が選択可能になるだけで何も意味はない。画面に様々な効果を付与するには、後述の Condition
と組み合わせる必要がある。
chart
に登録するときは add_selection
を使う。
alt.Chart(cars).mark_point().encode(
x='Miles_per_Gallon:Q',
y='Horsepower:Q',
color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))
).add_selection(
brush
)
実際に操作して試してほしいが、ドラッグして範囲を選択すると、その範囲だけが選択され、その範囲だけの値が右側に表示される。
Brushing Scatter Plot to show data on a table - Altair 3.2.0 documentation
Condition
Bindings, Selections, Conditions: Making Charts Interactive - Altair 3.2.0 documentation
brush = alt.selection(type='interval')
alt.Chart(cars).mark_point().encode(
x='Miles_per_Gallon:Q',
y='Horsepower:Q',
color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))
).add_selection(
brush
)
上記の例の場合、brush (selection) で選択されているエリアは True となり 'Origin:N'
をベースにした色付けがなされ、選択されていないエリアは False となり alt.value('lightgray')
色が使われる。
マーク
グラフの種類を規定するコンポーネント
mark_text
テキストの表示を規定する。グラフ上のラベルづけや表の作成などに使う。
import altair as alt
from vega_datasets import data
source = data.wheat()
bars = alt.Chart(source).mark_bar().encode(
x='wheat:Q',
y="year:O"
)
text = bars.mark_text(
align='left',
baseline='middle',
dx=3 # Nudges text to right so it doesn't appear on top of the bar
).encode(
text='wheat:Q'
)
(bars + text).properties(height=900)
Bar Chart with Labels - Altair 3.2.0 documentation
データ変換(transform)
Data Transformations - Altair 3.2.0 documentation
基本的には、AltairはAltairに来る前段階(つまりpandas DataFrame)でデータ変換処理を行うことを推奨している。しかし、データがJSON/CSVだった場合など、そうもいかない場合もある。また、同一のデータを複数の組み合わせのビューで閲覧したい場合もある。そこで、Altairはデータ変換のための関数群を用意している。
Window Transform
Data Transformations - Altair 3.2.0 documentation
transform_window()
を使うことで、 rank
や lag
といったウィンドウ関数を適用できる。
import altair as alt
from vega_datasets import data
alt.Chart(data.movies.url).transform_window(
sort=[{'field': 'IMDB_Rating'}],
frame=[None, 0],
cumulative_count='count(*)',
).mark_area().encode(
x='IMDB_Rating:Q',
y='cumulative_count:Q',
)
横軸全体 frame=[None, 0]
に対して、累積カウント cumulative_count='count(*)'
をしている。
Data Transformations - Altair 3.2.0 documentation
Filter Transform
Data Transformations - Altair 3.2.0 documentation
フィルタ機能。不要なデータを除去する。
import altair as alt
from altair import datum
from vega_datasets import data
pop = data.population.url
alt.Chart(pop).mark_area().encode(
x='age:O',
y='people:Q',
).transform_filter(
(datum.year == 2000) & (datum.sex == 1)
)
Data Transformations - Altair 3.2.0 documentation
ここでフィルタに Selection
を設定すると、選択した項目だけにフィルタされる。
brush = alt.selection(type='interval')
points = chart.mark_point().encode(
alt.Y('precision', title='Precision'),
alt.X('recall', title='Recall'),
color=alt.condition(brush, 'threshold', alt.value('grey'))
).add_selection(brush)
# Base chart for data tables
ranked_text = alt.Chart(df).mark_text().encode(
y=alt.Y('row_number:O',axis=None)
).transform_window(
row_number='row_number()'
).transform_filter(
brush
)
トップNでフィルタする
transform_filter(
(alt.datum.rank < 10)
)
複合チャート(Compound Chart)
水平結合(hconcat)
Compound Charts: Layer, HConcat, VConcat, Repeat, Facet - Altair 3.2.0 documentation
import altair as alt
from vega_datasets import data
iris = data.iris.url
chart1 = alt.Chart(iris).mark_point().encode(
x='petalLength:Q',
y='petalWidth:Q',
color='species:N'
).properties(
height=300,
width=300
)
chart2 = alt.Chart(iris).mark_bar().encode(
x='count()',
y=alt.Y('petalWidth:Q', bin=alt.Bin(maxbins=30)),
color='species:N'
).properties(
height=300,
width=100
)
chart1 | chart2
|
は hconcat
とも書ける。
alt.hconcat(chart1, chart2)
Tips
箱ひげ図(boxplot)における外れ値(outliers)の色は、カテゴリーごとに自動で色分けしてくれない
以下のような書き方をすると、箱は色分けしてくれるが外れ値は色分けしてくれない(デフォルトの色のまま)
alt.Chart(df).mark_boxplot().encode(
x="name:N",
y="value:Q",
color="category:N"
)
色分けするには別々にChartを作るしかない。
chart_cat1 = alt.Chart(df[df["category"] == "cat1"]).mark_boxplot(color="blue").encode(
x="name:N",
y="value:Q"
)
chart_cat2 = alt.Chart(df[df["category"] == "cat2"]).mark_boxplot(color="orange").encode(
x="name:N",
y="value:Q"
)
(chart_cat1 + chart_cat2)
参考
Apply color to outliers in boxplot · Issue #1591 · altair-viz/altair
Discussion