2. データ型、グラフィカルマーク、およびビジュアルエンコーディングチャネル#
可視化は、データを一連の_グラフィカルマーク_(棒、線、点など)を使用して表現します。マークの位置、形状、サイズ、色などの属性は、基礎となるデータ値をエンコードするための_チャネル_として機能します。
データ型、マーク、エンコーディングチャネルという基本的なフレームワークを使用することで、幅広い種類の可視化を簡潔に作成できます。このノートブックでは、これらの各要素を詳しく探り、それらを使用してカスタム統計グラフィックを作成する方法を示します。
このノートブックは、データ可視化カリキュラム の一部です。
import pandas as pd
import altair as alt
2.1. Global Development Data#
1955年から2005年までの期間にわたる、複数の国における世界の健康と人口に関するデータを可視化します。このデータはGapminder Foundationによって収集され、Hans Rosling氏の有名なTEDトークで共有されました。まだこのトークを見ていない方は、ぜひ最初にご覧ください!
まず、vega-datasetsコレクションからデータセットを読み込み、Pandasデータフレームに取り込みましょう。
from vega_datasets import data as vega_data
data = vega_data.gapminder()
データのサイズはどれくらいでしょうか?
data.shape
(693, 6)
693行と6列です!データの内容を少し覗いてみましょう:
data.head(5)
year | country | cluster | pop | life_expect | fertility | |
---|---|---|---|---|---|---|
0 | 1955 | Afghanistan | 0 | 8891209 | 30.332 | 7.7 |
1 | 1960 | Afghanistan | 0 | 9829450 | 31.997 | 7.7 |
2 | 1965 | Afghanistan | 0 | 10997885 | 34.020 | 7.7 |
3 | 1970 | Afghanistan | 0 | 12430623 | 36.088 | 7.7 |
4 | 1975 | Afghanistan | 0 | 14132019 | 38.438 | 7.7 |
各country
(国)とyear
(5年ごとの間隔)について、以下の指標が含まれています:
1人の女性あたりの子どもの数を表す出生率(
fertility
)年数で表した平均寿命(
life_expect
)総人口(
pop
)
さらに、cluster
フィールドには整数コードが含まれています。これが何を表しているのか、データを可視化しながらこの謎を解き明かしてみましょう!
Let’s also create a smaller data frame, filtered down to values for the year 2000 only:
以下のように、2000年の値に絞り込んだ小さいデータフレームを作成しましょう:
data2000 = data.loc[data['year'] == 2000]
data2000.head(5)
year | country | cluster | pop | life_expect | fertility | |
---|---|---|---|---|---|---|
9 | 2000 | Afghanistan | 0 | 23898198 | 42.129 | 7.4792 |
20 | 2000 | Argentina | 3 | 37497728 | 74.340 | 2.3500 |
31 | 2000 | Aruba | 3 | 69539 | 73.451 | 2.1240 |
42 | 2000 | Australia | 4 | 19164620 | 80.370 | 1.7560 |
53 | 2000 | Austria | 1 | 8113413 | 78.980 | 1.3820 |
2.2. データ型#
効果的な可視化の最初の要素は入力データです。データ値はさまざまな測定形式を表すことができます。それらの測定がどのような比較をサポートするか、またそれに応じた視覚エンコーディングをどのようにサポートするかを考える必要があります。
ここでは、Altairが視覚エンコーディングの選択に役立てる基本的なデータ型について説明します。これらのデータ型は、可能な比較の種類を決定し、それにより可視化デザインの決定を導きます。
2.2.1. 名義型 (N)#
名義型(カテゴリ型とも呼ばれる)は、カテゴリ名から成るデータです。
名義型データでは、値が等しいかどうかを比較できます:値Aは値Bと同じか、それとも異なるか?(A = B)。例えば、「AはBと等しい」または「AはBと等しくない」という主張をサポートします。上記のデータセットでは、country
フィールドが名義型です。
名義型データを可視化する際には、値が同じか異なるかを簡単に判別できる必要があります。位置、色相(青、赤、緑など)、形状が役立ちます。ただし、サイズチャネルを名義型データに使用すると、存在しないランク順や大きさの違いを示唆する可能性があるため、誤解を招くかもしれません!
2.2.2. 順序型 (O)#
順序型データは、特定の順序を持つ値から成ります。
順序型データでは、値のランク順を比較できます:値Aは値Bの前に来るか後に来るか?(A < B)。例えば、「AはBより小さい」または「AはBより大きい」という主張をサポートします。上記のデータセットでは、year
フィールドを順序型として扱うことができます。
順序型データを可視化する際には、ランク順が感覚的にわかるようにする必要があります。位置、サイズ、または色の明るさ(輝度)が適切ですが、色相(知覚的な順序がないため)はあまり適切ではありません。
2.2.3. 量的型 (Q)#
量的型データでは、値間の数値的な違いを測定できます。量的データにはいくつかのサブタイプがあります:
間隔型データでは、ポイント間の距離(間隔)を測定できます:値Aは値Bからどれだけ離れているか?(A - B)。例えば、「AはBから12単位離れている」という主張をサポートします。
比率型データでは、ゼロポイントに意味があるため、比率やスケール係数を測定できます:値Aは値Bの何倍か?(A / B)。例えば、「AはBの10%である」または「BはAの7倍大きい」という主張をサポートします。
上記のデータセットでは、year
は量的な間隔型フィールド(「年0」の値は主観的)ですが、fertility
やlife_expect
は量的な比率型フィールド(ゼロに意味があり、比率計算が可能)です。Vega-Liteは量的データを表しますが、間隔型と比率型の区別は行いません。
量的値は、位置、サイズ、色の明るさなどのチャネルを使用して可視化できます。比率値の比例比較にはゼロ基準の軸が重要ですが、間隔比較では省略可能です。
2.2.4. 時間型 (T)#
時間型データは、時間のポイントまたは間隔を測定します。この型は量的値(タイムスタンプ)の特殊なケースであり、豊富なセマンティクスと慣例(例:グレゴリオ暦)を持っています。Vega-Liteの時間型は、時間単位(年、月、日、時など)についての推論をサポートし、特定の時間間隔を要求するためのメソッドを提供します。
例として、"2019-01-04"
や"Jan 04 2019"
といった日付文字列、またはISO日付形式の"2019-01-04T17:50:35.643Z"
などがあります。
上記の世界開発データセットには、year
フィールドが単なる整数としてエンコードされているため、時間型の値は含まれていません。Altairで時間型データを使用する詳細については、時刻と日付に関するドキュメントをご覧ください。
2.2.5. まとめ#
これらのデータ型は互いに排他的ではなく、階層を形成します:順序型データは名義型(等式)比較をサポートし、量的データは順序型(ランク順)比較をサポートします。
さらに、これらのデータ型は固定的な分類を提供するものではありません。例えば、データフィールドが数値で表現されているからといって、必ずしも量的型として扱う必要はありません。例えば、一連の年齢(10歳、20歳など)を名義型(未成年か成年か)、順序型(年ごとにグループ化)、または量的型(平均年齢を計算)として解釈することができます。
それでは、これらのデータ型をどのように視覚的にエンコードするかを見ていきましょう!
2.3. エンコーディングチャネル#
Altairの中心となるのは、データフィールド(特定のデータ型を持つ)を、選択したマークタイプの利用可能なエンコーディングチャネルに結び付けるエンコーディングの利用です。このノートブックでは、次のエンコーディングチャネルについて説明します:
x
: マークの水平位置(x軸)。y
: マークの垂直位置(y軸)。size
: マークのサイズ。マークのタイプによって面積または長さに対応します。color
: マークの色。有効なCSSカラーとして指定します。opacity
: マークの不透明度。0(完全に透明)から1(完全に不透明)の範囲で指定します。shape
:point
マークのプロット記号の形状。tooltip
: マウスホバー時に表示されるツールチップテキスト。order
: マークの順序。線/エリアのポイント順序や描画順序を決定します。column
: データを水平方向に揃えたサブプロットに分割します。row
: データを垂直方向に揃えたサブプロットに分割します。
利用可能なチャネルの完全なリストについては、Altairエンコーディングドキュメントを参照してください。
2.3.1. X#
x
エンコーディングチャネルは、マークの水平位置(x座標)を設定します。また、軸やタイトルのデフォルト設定が自動的に選択されます。以下のチャートでは、量的データ型を選択した結果、連続的な線形軸スケールが使用されています:
alt.Chart(data2000).mark_point().encode(
alt.X('fertility:Q')
)
2.3.2. Y#
y
エンコーディングチャネルは、マークの垂直位置(y座標)を設定します。ここでは、cluster
フィールドを順序型(O
)のデータ型として追加しました。その結果、各ユニークな値に対してサイズ付きのバンドを持つ離散軸が生成され、デフォルトのステップサイズが適用されています:
alt.Chart(data2000).mark_point().encode(
alt.X('fertility:Q'),
alt.Y('cluster:O')
)
上記のチャートで、O
型とQ
型を入れ替えるとどうなるでしょうか?
代わりに、life_expect
フィールドを量的(Q
)変数として追加すると、両方の軸が線形スケールを持つ散布図が生成されます:
alt.Chart(data2000).mark_point().encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q')
)
デフォルトでは、量的な線形スケールの軸にはゼロが含まれ、比率データの適切な基準線が確保されます。ただし、場合によっては、ゼロ基準が意味を持たない場合や、間隔の比較に焦点を当てたい場合があります。ゼロの自動挿入を無効にするには、エンコーディングのscale
属性を使用してスケールマッピングを設定します:
alt.Chart(data2000).mark_point().encode(
alt.X('fertility:Q', scale=alt.Scale(zero=False)),
alt.Y('life_expect:Q', scale=alt.Scale(zero=False))
)
これで、軸スケールにゼロが含まれなくなりました。ただし、軸のドメイン(範囲)の終端は、自動的に5や10などの きりの良い 数値に調整されるため、若干の余白が残ります。
上記のスケール属性にさらにnice=False
を追加するとどうなるでしょうか?
2.3.3. サイズ#
size
エンコーディングチャネルは、マークのサイズや範囲を設定します。このチャネルの意味は、マークの種類に応じて変化します。例えば、point
マークの場合、size
チャネルはプロット記号のピクセル面積にマッピングされます。そのため、ポイントの直径はサイズ値の平方根に一致します。
散布図を拡張し、size
チャネルに人口(pop
)をエンコードしてみましょう。その結果、サイズ値を解釈するための凡例もチャートに追加されます。
alt.Chart(data2000).mark_point().encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q')
)
場合によっては、デフォルトのサイズ範囲に満足できないこともあります。カスタマイズしたサイズの範囲を指定するには、scale
属性のrange
パラメータを設定し、最小サイズと最大サイズを示す配列を指定します。
ここでは、サイズエンコーディングを更新し、ゼロ値の場合は0ピクセル、スケールドメイン内の最大値の場合は1,000ピクセルに設定してみましょう:
alt.Chart(data2000).mark_point().encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000]))
)
2.3.4. 色と不透明度#
color
エンコーディングチャネルは、マークの色を設定します。色のエンコーディングスタイルはデータ型に大きく依存します。名義型データの場合は、通常、複数の色相を持つ定性的なカラースキームが使用されます。一方、順序型や量的データでは、知覚的に順序付けられた色のグラデーションが使用されます。
ここでは、color
チャネルと名義型(N
)データ型を使用してcluster
フィールドをエンコードし、各クラスタ値に異なる色相を割り当てます。cluster
フィールドが何を示しているか、推測し始めることができますか?
alt.Chart(data2000).mark_point().encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000])),
alt.Color('cluster:N')
)
塗りつぶした形状を使用したい場合、mark_point
メソッドにfilled=True
パラメータを渡すことができます:
alt.Chart(data2000).mark_point(filled=True).encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000])),
alt.Color('cluster:N')
)
デフォルトでは、Altairはプロットの重なりを軽減するために、わずかに透明度を適用します。透明度は、mark_*
メソッドにデフォルト値を渡すか、専用のエンコーディングチャネルを使用してさらに調整することができます。
ここでは、データフィールドをバインドする代わりに、エンコーディングチャネルに一定の値を提供する方法を示します:
alt.Chart(data2000).mark_point(filled=True).encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000])),
alt.Color('cluster:N'),
alt.OpacityValue(0.5)
)
2.3.5. 形状#
shape
エンコーディングチャネルは、point
マークで使用される幾何学的な形状を設定します。これまでに見た他のチャネルとは異なり、shape
チャネルは他のマークタイプでは使用できません。また、shape
エンコーディングチャネルは名義型データでのみ使用するべきです。なぜなら、知覚的なランク順や大きさの比較には対応していないためです。
ここでは、cluster
フィールドをshape
とcolor
の両方でエンコードしてみましょう。同じ基礎データフィールドに複数のチャネルを使用することは、冗長エンコーディングと呼ばれます。この結果として得られるチャートは、色と形状の情報を組み合わせた単一のシンボル凡例を持ちます:
alt.Chart(data2000).mark_point(filled=True).encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000])),
alt.Color('cluster:N'),
alt.OpacityValue(0.5),
alt.Shape('cluster:N')
)
2.3.6. ツールチップと順序#
ここまで進めると、少しもどかしさを感じるかもしれません。チャートを構築してきましたが、可視化されたポイントがどの国に対応しているのかまだ分からないからです!インタラクティブなツールチップを追加して、探索を可能にしましょう。
tooltip
エンコーディングチャネルは、ユーザーがマークにマウスカーソルを移動したときに表示されるツールチップテキストを決定します。country
フィールドのツールチップエンコーディングを追加して、どの国が表されているのか調べてみましょう。
alt.Chart(data2000).mark_point(filled=True).encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000])),
alt.Color('cluster:N'),
alt.OpacityValue(0.5),
alt.Tooltip('country')
)
マウスを動かしていると、一部のポイントを選択できないことに気付くかもしれません。例えば、最も大きな濃い青色の円はインドを表しており、より小さい人口の国の上に描画されているため、その国の上にマウスをホバーできません。この問題を解決するには、order
エンコーディングチャネルを使用します。
order
エンコーディングチャネルは、データポイントの順序を決定します。これにより、描画の順序や、line
およびarea
マークにおけるポイント同士の接続順序に影響を与えます。
ここでは、人口(pop
)による降順で値を並べ替え、大きな円の後に小さな円が描画されるように設定してみましょう:
alt.Chart(data2000).mark_point(filled=True).encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000])),
alt.Color('cluster:N'),
alt.OpacityValue(0.5),
alt.Tooltip('country:N'),
alt.Order('pop:Q', sort='descending')
)
これで、インドによって隠されていた小さな国を特定できました。それはバングラデシュです!
また、cluster
フィールドが何を表しているかも推測できるようになります。さまざまな色のポイントにマウスをホバーして、自分なりの説明を考えてみてください。
ここまでで、ツールチップに基礎データレコードの単一プロパティを表示するようにしました。複数の値を表示するには、tooltip
チャネルにエンコーディングの配列を渡します。この配列には、表示したい各フィールドを指定します:
alt.Chart(data2000).mark_point(filled=True).encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000])),
alt.Color('cluster:N'),
alt.OpacityValue(0.5),
alt.Order('pop:Q', sort='descending'),
tooltip = [
alt.Tooltip('country:N'),
alt.Tooltip('fertility:Q'),
alt.Tooltip('life_expect:Q')
]
)
これで、マウスホバー時に複数のデータフィールドを表示できるようになりました!
2.3.7. 列と行のファセット#
空間的な位置は視覚エンコーディングにおいて最も強力で柔軟なチャネルの1つですが、すでにフィールドをx
とy
チャネルに割り当てている場合はどうすればよいでしょうか?有用な手法の1つは、データのサブセットを表示するサブプロットからなるトレリスプロットを作成することです。トレリスプロットは、データをスモールマルチプルのビューで表示する一般的な手法の一例です。
column
とrow
エンコーディングチャネルは、指定されたデータフィールドに従ってデータを分割し、横方向(列)または縦方向(行)にサブプロットを生成します。
以下は、データをcluster
の値ごとに1列に分割したトレリスプロットの例です:
alt.Chart(data2000).mark_point(filled=True).encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000])),
alt.Color('cluster:N'),
alt.OpacityValue(0.5),
alt.Tooltip('country:N'),
alt.Order('pop:Q', sort='descending'),
alt.Column('cluster:N')
)
上記のプロットは画面に収まりきらず、すべてのサブプロットを比較するのが難しくなっています。デフォルトのwidth
とheight
プロパティを設定して、より小さなスモールマルチプルを作成できます。また、列ヘッダーがすでにcluster
の値をラベルとして表示しているため、color
の凡例をNone
に設定して削除しましょう。さらに、スペースを有効活用するために、size
の凡例をチャートの'bottom'
に配置するよう設定することもできます。
alt.Chart(data2000).mark_point(filled=True).encode(
alt.X('fertility:Q'),
alt.Y('life_expect:Q'),
alt.Size('pop:Q', scale=alt.Scale(range=[0,1000]),
legend=alt.Legend(orient='bottom', titleOrient='left')),
alt.Color('cluster:N', legend=None),
alt.OpacityValue(0.5),
alt.Tooltip('country:N'),
alt.Order('pop:Q', sort='descending'),
alt.Column('cluster:N')
).properties(width=135, height=135)
column
とrow
のエンコーディングは、内部的にはfacet
ビュー構成オペレーターを使用する新しい仕様に変換されます。このfacet
については後ほどさらに詳しく取り上げます!
それまでの間に、上記のチャートを列ではなく行に分割するように書き換えることができますか?
2.3.8. 先取り: インタラクティブフィルタリング#
後のモジュールでは、データ探索のためのインタラクション手法を詳しく学びます。ここではその先取りとして、year
フィールドにレンジスライダーをバインドし、各年のデータをインタラクティブにスクラブできる機能を紹介します。この時点で以下のコードが少し難しく感じられても心配しないでください。後でインタラクションについて詳しく説明します。
スライダーを前後に動かして、データ値が時間とともにどのように変化するかを確認してください!
select_year = alt.selection_single(
name='select', fields=['year'], init={'year': 1955},
bind=alt.binding_range(min=1955, max=2005, step=5)
)
alt.Chart(data).mark_point(filled=True).encode(
alt.X('fertility:Q', scale=alt.Scale(domain=[0,9])),
alt.Y('life_expect:Q', scale=alt.Scale(domain=[0,90])),
alt.Size('pop:Q', scale=alt.Scale(domain=[0, 1200000000], range=[0,1000])),
alt.Color('cluster:N', legend=None),
alt.OpacityValue(0.5),
alt.Tooltip('country:N'),
alt.Order('pop:Q', sort='descending')
).add_selection(select_year).transform_filter(select_year)
/Users/yuichiyazaki/.pyenv/versions/miniforge3-4.10.3-10/lib/python3.9/site-packages/altair/utils/deprecation.py:65: AltairDeprecationWarning: 'selection_single' is deprecated. Use 'selection_point'
warnings.warn(message, AltairDeprecationWarning, stacklevel=1)
/Users/yuichiyazaki/.pyenv/versions/miniforge3-4.10.3-10/lib/python3.9/site-packages/altair/vegalite/v5/api.py:417: AltairDeprecationWarning: Use 'value' instead of 'init'.
warnings.warn(
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In [22], line 1
----> 1 select_year = alt.selection_single(
2 name='select', fields=['year'], init={'year': 1955},
3 bind=alt.binding_range(min=1955, max=2005, step=5)
4 )
6 alt.Chart(data).mark_point(filled=True).encode(
7 alt.X('fertility:Q', scale=alt.Scale(domain=[0,9])),
8 alt.Y('life_expect:Q', scale=alt.Scale(domain=[0,90])),
(...)
13 alt.Order('pop:Q', sort='descending')
14 ).add_selection(select_year).transform_filter(select_year)
File ~/.pyenv/versions/miniforge3-4.10.3-10/lib/python3.9/site-packages/altair/utils/deprecation.py:66, in _deprecate.<locals>.new_obj(*args, **kwargs)
63 @functools.wraps(obj)
64 def new_obj(*args, **kwargs):
65 warnings.warn(message, AltairDeprecationWarning, stacklevel=1)
---> 66 return obj(*args, **kwargs)
File ~/.pyenv/versions/miniforge3-4.10.3-10/lib/python3.9/site-packages/altair/vegalite/v5/api.py:753, in selection_single(**kwargs)
747 @utils.deprecation.deprecated(
748 message="'selection_single' is deprecated. Use 'selection_point'"
749 )
750 @utils.use_signature(core.PointSelectionConfig)
751 def selection_single(**kwargs):
752 """'selection_single' is deprecated. Use 'selection_point'"""
--> 753 return _selection(type="point", **kwargs)
File ~/.pyenv/versions/miniforge3-4.10.3-10/lib/python3.9/site-packages/altair/vegalite/v5/api.py:478, in _selection(type, **kwds)
475 else:
476 raise ValueError("""'type' must be 'point' or 'interval'""")
--> 478 return param(select=select, **param_kwds)
File ~/.pyenv/versions/miniforge3-4.10.3-10/lib/python3.9/site-packages/altair/vegalite/v5/api.py:444, in param(name, value, bind, empty, expr, **kwds)
442 parameter.param_type = "selection"
443 else:
--> 444 parameter.param = core.SelectionParameter(
445 name=parameter.name, bind=bind, value=value, expr=expr, **kwds
446 )
447 parameter.param_type = "selection"
449 return parameter
TypeError: altair.vegalite.v5.schema.core.SelectionParameter() got multiple values for keyword argument 'value'
2.4. グラフィカルマーク#
上記でエンコーディングチャネルを探求する際には、point
マークを使用してデータを可視化してきました。しかし、point
マークはデータを視覚的に表現するために使用できる多くの幾何学的形状の1つに過ぎません。Altairには、以下を含む多くの組み込みマークタイプが用意されています:
mark_area()
- トップラインとベースラインで定義された塗りつぶしエリア。mark_bar()
- 長方形の棒グラフ。mark_circle()
- 散布図のポイントとして使用される塗りつぶした円。mark_line()
- 接続された線分。mark_point()
- 形状を設定可能な散布図のポイント。mark_rect()
- 塗りつぶされた長方形(ヒートマップに便利)。mark_rule()
- 軸をまたぐ垂直または水平の線。mark_square()
- 散布図のポイントとして使用される塗りつぶした四角形。mark_text()
- テキストで表現された散布図のポイント。mark_tick()
- 垂直または水平の目盛り線。
完全なリストや例へのリンクについては、Altairマークのドキュメントを参照してください。次に、統計グラフィックで最も一般的に使用されるマークタイプをいくつか順に紹介します。
2.4.1. ポイントマーク#
point
マークタイプは、散布図やドットプロットのように特定のポイントを表現します。x
およびy
エンコーディングチャネル(2Dポイントの位置を指定)に加えて、point
マークはcolor
、size
、shape
のエンコーディングを使用して追加のデータフィールドを伝達できます。
以下は、fertility
のドットプロットで、cluster
フィールドをy
とshape
チャネルの両方で冗長的にエンコードしています。
alt.Chart(data2000).mark_point().encode(
alt.X('fertility:Q'),
alt.Y('cluster:N'),
alt.Shape('cluster:N')
)
エンコーディングチャネルに加えて、mark_*()
メソッドに値を渡すことでマークをスタイリングすることができます。
例えば、ポイントマークはデフォルトではアウトライン付きで描画されますが、filled
形状を使用するように指定することも可能です。同様に、デフォルトのsize
を設定してポイントマークの総ピクセル面積を指定することもできます。
alt.Chart(data2000).mark_point(filled=True, size=100).encode(
alt.X('fertility:Q'),
alt.Y('cluster:N'),
alt.Shape('cluster:N')
)
2.4.2. サークルマーク#
circle
マークタイプは、塗りつぶされた円として描画されるpoint
マークの便利な省略形です。
alt.Chart(data2000).mark_circle(size=100).encode(
alt.X('fertility:Q'),
alt.Y('cluster:N'),
alt.Shape('cluster:N')
)
2.4.3. スクエアマーク#
square
マークタイプは、塗りつぶされた四角形として描画されるpoint
マークの便利な省略形です。
alt.Chart(data2000).mark_square(size=100).encode(
alt.X('fertility:Q'),
alt.Y('cluster:N'),
alt.Shape('cluster:N')
)
2.4.4. ティックマーク#
tick
マークタイプは、短い線分または「目盛り」を使用してデータポイントを表現します。これらは、1次元に沿った値を最小限の重なりで比較するのに特に有用です。ティックマークで描画されたドットプロットは、ストリッププロットと呼ばれることもあります。
alt.Chart(data2000).mark_tick().encode(
alt.X('fertility:Q'),
alt.Y('cluster:N'),
alt.Shape('cluster:N')
)
2.4.5. バーマーク#
bar
マークタイプは、位置、幅、高さを持つ長方形を描画します。
以下のプロットは、各国の人口(pop
)を示すシンプルな棒グラフです。
alt.Chart(data2000).mark_bar().encode(
alt.X('country:N'),
alt.Y('pop:Q')
)
棒の幅はデフォルトのサイズに設定されています。棒の幅を調整する方法については、このノートブックの後半で説明します。(軸、スケール、および凡例の設定に関しては、後のノートブックで詳しく見ていきます。)
棒を積み重ねることも可能です。x
エンコーディングをcluster
フィールドに変更し、country
をcolor
チャネルでエンコードしてみましょう。また、すべての国の色を表示すると凡例が非常に長くなるため、凡例を無効にし、国名を表示するためにツールチップを使用します。
alt.Chart(data2000).mark_bar().encode(
alt.X('cluster:N'),
alt.Y('pop:Q'),
alt.Color('country:N', legend=None),
alt.Tooltip('country:N')
)
上記のチャートでは、color
エンコーディングチャネルの使用により、Altair / Vega-Liteが自動的にバーを積み重ねています。これがなければ、バーが互いに重なって描画されてしまいます!y
エンコーディングチャネルにパラメータstack=None
を追加して、積み重ねを適用しない場合に何が起こるか試してみてください…
上記の例では、棒グラフはゼロ基準から作成されており、y
チャネルは非ゼロ値(または棒の高さ)のみをエンコードしています。しかし、バーのマークでは、範囲を表現するために開始点と終了点を指定することも可能です。
以下のチャートでは、x
(開始点)とx2
(終了点)チャネルを使用して、各地域クラスター内の平均寿命の範囲を示しています。この例では、範囲の終端を決定するためにmin
とmax
の集計関数を使用しています。集計については、次のノートブックで詳しく説明します!
また、x
とwidth
を使用して、開始点とオフセットを指定することで、x2 = x + width
のように終了点を設定することもできます。
alt.Chart(data2000).mark_bar().encode(
alt.X('min(life_expect):Q'),
alt.X2('max(life_expect):Q'),
alt.Y('cluster:N')
)
2.4.6. ラインマーク#
line
マークタイプは、プロットされたポイントを線分で接続します。例えば、線の傾きが変化率に関する情報を伝えるために使用されます。
ここでは、フィルタリングされていない世界開発データフレーム全体を使用して、年ごとの各国の出生率を示すラインチャートを作成します。凡例は非表示にし、代わりにツールチップを使用します。
alt.Chart(data).mark_line().encode(
alt.X('year:O'),
alt.Y('fertility:Q'),
alt.Color('country:N', legend=None),
alt.Tooltip('country:N')
).properties(
width=400
)
国ごとに興味深い変動が見られますが、全体としては家族あたりの子どもの数が時間とともに減少する傾向が確認できます。また、幅を400ピクセルにカスタマイズした点にも注目してください。幅を変更または削除して、どのように変化するか試してみてください!
次に、デフォルトのマークパラメータを変更してプロットをカスタマイズします。strokeWidth
を設定して線の太さを決定し、opacity
で透明度を追加することができます。デフォルトでは、line
マークはデータポイントを直線で接続しますが、場合によっては線を滑らかにしたいこともあります。データポイントを接続する際の補間方法は、interpolate
マークパラメータを設定することで調整できます。ここでは、滑らかな線を提供すると同時に補間によって「偽の」最小値や最大値が生成されないよう保証する'monotone'
補間を使用します。
alt.Chart(data).mark_line(
strokeWidth=3,
opacity=0.5,
interpolate='monotone'
).encode(
alt.X('year:O'),
alt.Y('fertility:Q'),
alt.Color('country:N', legend=None),
alt.Tooltip('country:N')
).properties(
width=400
)
line
マークは、スロープグラフを作成するためにも使用できます。スロープグラフは、2つの比較ポイント間の値の変化を線の傾きで強調するチャートです。
以下では、データセット全体の最小年(1955年)と最大年(2005年)における各国の人口を比較するスロープグラフを作成します。まず、それらの年に絞り込んだ新しいPandasデータフレームを作成し、その後Altairを使用してスロープグラフを作成します。
デフォルトでは、Altairは年をx軸上で近接して配置します。x軸上の年をより適切に間隔を空けて配置するために、以下のコメントで示されているように、チャートの幅における離散的なステップのサイズ(ピクセル単位)を指定できます。以下のstep
値を調整して、チャートがどのように変化するかを確認してみてください。
dataTime = data.loc[(data['year'] == 1955) | (data['year'] == 2005)]
alt.Chart(dataTime).mark_line(opacity=0.5).encode(
alt.X('year:O'),
alt.Y('pop:Q'),
alt.Color('country:N', legend=None),
alt.Tooltip('country:N')
).properties(
width={"step": 50} # adjust the step parameter
)
2.4.7. エリアマーク#
area
マークタイプは、line
マークとbar
マークの特徴を組み合わせています。データポイント間の接続(傾き)を視覚化すると同時に、塗りつぶされた領域も表示します。この塗りつぶし領域の1つの端は、デフォルトでゼロ値の基準線に設定されます。
以下のチャートは、アメリカ合衆国における時間の経過に伴う人口を示すエリアチャートです:
dataUS = data.loc[data['country'] == 'United States']
alt.Chart(dataUS).mark_area().encode(
alt.X('year:O'),
alt.Y('fertility:Q')
)
line
マークと同様に、area
マークもinterpolate
パラメータをサポートしています。
alt.Chart(dataUS).mark_area(interpolate='monotone').encode(
alt.X('year:O'),
alt.Y('fertility:Q')
)
bar
マークと同様に、area
マークも積み重ねをサポートしています。ここでは、北米の3か国のデータを含む新しいデータフレームを作成し、それをarea
マークとcolor
エンコーディングチャネルを使用して、国ごとに積み重ねたチャートを作成します。
dataNA = data.loc[
(data['country'] == 'United States') |
(data['country'] == 'Canada') |
(data['country'] == 'Mexico')
]
alt.Chart(dataNA).mark_area().encode(
alt.X('year:O'),
alt.Y('pop:Q'),
alt.Color('country:N')
)
デフォルトでは、積み重ねはゼロ基準に対して行われます。ただし、他のstack
オプションも利用可能です:
center
- チャートの中央に基準線を設定し、ストリームグラフのビジュアライゼーションを作成。normalize
- 各積み重ねポイントで合計データを100%に正規化し、割合比較を可能にします。
以下では、y
エンコーディングのstack
属性をcenter
に設定してチャートを調整します。代わりにnormalize
を設定すると、どのように変化するでしょうか?
alt.Chart(dataNA).mark_area().encode(
alt.X('year:O'),
alt.Y('pop:Q', stack='center'),
alt.Color('country:N')
)
積み重ねを完全に無効にするには、stack
属性をNone
に設定します。また、デフォルトのマークパラメータとしてopacity
を追加することで、重なり合った領域を視認しやすくすることができます!
alt.Chart(dataNA).mark_area(opacity=0.5).encode(
alt.X('year:O'),
alt.Y('pop:Q', stack=None),
alt.Color('country:N')
)
area
マークタイプは、データに基づいた基準線もサポートしており、上下の系列がデータフィールドによって決定されます。bar
マークと同様に、x
とx2
(またはy
とy2
)チャネルを使用して、エリアマークの終端ポイントを指定することができます。
以下のチャートは、北米諸国における年ごとの出生率の最小値と最大値の範囲を可視化しています:
alt.Chart(dataNA).mark_area().encode(
alt.X('year:O'),
alt.Y('min(fertility):Q'),
alt.Y2('max(fertility):Q')
).properties(
width={"step": 40}
)
1995年には、約4未満から約7未満までの広い範囲の値が見られます。一方、2005年には出生率全体の値とその変動幅が共に減少し、家族あたり子ども2人を中心に収束していることがわかります.
上記のすべてのarea
マークの例では、縦方向のエリアを使用しています。しかし、AltairとVega-Liteは横方向のエリアもサポートしています。x
チャネルとy
チャネルを入れ替えるだけで、上記のチャートを横方向に変換してみましょう。
alt.Chart(dataNA).mark_area().encode(
alt.Y('year:O'),
alt.X('min(fertility):Q'),
alt.X2('max(fertility):Q')
).properties(
width={"step": 40}
)
2.5. まとめ#
データ型、エンコーディングチャネル、グラフィカルマークの探索を完了しました!これで、エンコーディング、マークタイプ、およびマークパラメータの世界をさらに探求する準備が整いました。より包括的なリファレンス(ここで省略した機能も含む!)については、Altairのマークとエンコーディングのドキュメントをご覧ください。
次のモジュールでは、データを要約したり、新しい派生フィールドを可視化したりするためのデータ変換の使用方法を見ていきます。また、後のモジュールでは、スケール、軸、凡例を変更してチャートをさらにカスタマイズする方法を学びます。
視覚エンコーディングについてもっと学びたいですか?
Mike Bostockによる適応版、Sémiologie Graphiqueからのベルタンの視覚エンコーディング分類。
マーク、視覚エンコーディング、および基盤となるデータ型の体系的な研究は、ジャック・ベルタン (Jacques Bertin)が1967年に発表した先駆的な著書 Sémiologie Graphique (グラフィックの記号論) によって始まりました。上記の画像は、位置、サイズ、値(明るさ)、テクスチャ、色相、向き、形状チャネルを示し、それらがサポートするデータ型に関するベルタンの推奨を説明しています。
データ型、マーク、チャネルのフレームワークは、1986年に発表されたMackinlayのAPT (A Presentation Tool)を皮切りに、VoyagerやDracoのような近年のシステムに至るまで、_自動化_された可視化デザインツールにも影響を与えています。
名義型、順序型、間隔型、比率型の識別は、少なくともS. S. Stevenが1947年に発表した記事 On the theory of scales of measurement までさかのぼります。