Vega解説 〜離散データ〜

## 概要

Vega はjsonでデータや描画の設定を記述することで、視覚化できるツールです。
ただ、このjsonはぱっと見複雑なため、Vega自体の敷居を高くしてしまっている気がします。
そこで、とてもシンプルなグラフでjsonの構造を解説し敷居を下げていければなぁと思っています。


## 棒グラフ

以下がチュートリアルの棒グラフをさらに単純化したものです。

![visualization.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51316/b57e84d9-5bd6-fa7b-4da2-b2a1d2855aa0.png)
[Online Vega Editorで開く](https://vega.github.io/editor/#/gist/54fcc244e57c652c3d4d227881fcdecc/01_barchart_base.json)

ざっくりと次のような構成になっています。`プロパティ($schema,width..)`, `data`、`scales`、`axes`、`marks`です。

### プロパティ

スキーマとか、幅・高さとかを指定してます。

```
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "width": 400,
  "height": 200,
  "padding": 5,
```

### data

グラフの元データを指定します。

```
"data": [
    {
      "name": "table",
      "values": [
        {"category": "A", "amount": 28},
        {"category": "B", "amount": 55},
        {"category": "C", "amount": 43}
      ]
    }
  ],
```

今回は`category` と`amount`という値をもった３つのデータを定義してます。
ここでデータに対して、フィルターや集計などの操作も定義できますが、 長くなりすぎるので今回はスルーします。



### scales

数値や日付、文字列データを視覚化するための値にマッピングします。




```
"scales": [
    {
      "name": "xscale",
      "type": "band",
      "domain": {"data": "table", "field": "category"},
      "range": "width",
      "padding": 0.2,
      "round": true
    },
    {
      "name": "yscale",
      "domain": {"data": "table", "field": "amount"},
      "range": "height"
    }
  ],
```


まず、`xscale`という名前で、`category` に対してtypeが`band` のscaleとして設定します。
`band`は、以下のような構造でマッピングされます。`range`が、jsonの一番上で指定した`width`を指定しており、x方向のピクセル座標[0,400]になります。データの`category`が三種類(A,B,C)なので、各bandの位置が計算できるようになります(A: 25-125, B:150-250, C:275-375)。
![Band Scale](https://raw.githubusercontent.com/d3/d3-scale/master/img/band.png)
ちなみにこの図は、[d3のスケールのドキュメント](https://github.com/d3/d3-scale#band-scales)を参照しています。

`yscale` という名前で、`amount`に対して `linear` (線形：デフォルト）のscaleとなります。
`range`にheightを指定しており、[`amount`の最大値, 0]がy方向のピクセル座標[0,200]にマッピングされます。

### axes

軸に対して、scaleを関連付けします。

```
  "axes": [
    { "orient": "bottom", "scale": "xscale" },
    { "orient": "left", "scale": "yscale" }
  ],
```


### marks

図の定義をしてます。
`type`を`rect`を指定しており、長方形の図を指定しています。
`rect` は、x,x2(or width), y,y2(or height)とかで場所を指定します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51316/5516d707-6016-c3d1-e350-e6e8aa75a160.png)

```
"marks": [
    {
      "name": "layer_0",
      "type": "rect",
      "from": {"data":"table"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "category"},
          "width": {"scale":"xscale", "band":1},
          "y": {"scale": "yscale", "field": "amount"},
          "y2": {"scale": "yscale", "value": 0},
          "fill": {"value": "steelblue"}
        }
      }
    }
  ]
```

fromとして、data`table`を指定しており、`table` の各データ(今回は３つ）に対してencode処理されます。
ピクセル座標のy軸とyscaleの方向が逆になっているので、y2が０になっています。(yscaleの0がピクセルy座標での200、yscaleの55がピクセルy座標の0になる）

例えば、`{"category": "A", "amount": 28}`に対して、次のようなピクセル座標の変換がされます。

* x=25 : xscaleのAの位置でのピクセル位置
* width=100 : xscaleのbandの長さ
* y=98.181818 : 200-(200/55)*28
* y2=200 : 200-(200/55)*0

`name`を指定しておくと`vega editor`のDATA VIEWER で各データごとの詳細を確認することができます。

こんな感じで、グラフが描画されるようになります。



## 散布図っぽく

ちょっと変えるだけで、散布図っぽくなります。

![visualization (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51316/c740aa61-b4db-7c06-ca97-9677f4398f0e.png)

[Online Vega Editorで開く](https://vega.github.io/editor/#/gist/54fcc244e57c652c3d4d227881fcdecc/02_pointchart_base.json)

* xscale を`band`から、`point`に
* markのtypeを`rect`から`symbol`にし、不要なwidth, y2を削除


```diff
20c20
<       "type": "band",
---
>       "type": "point",
39c39
<       "type": "rect",
---
>       "type": "symbol",
44d43
<           "width": {"scale":"xscale", "band":1},
46d44
<           "y2": {"scale": "yscale", "value": 0},
52a51

```


## [おまけ] 図形を重ねてみる

markは、複数指定でき、後ろで指定したものが前面になります。

例えば、一つ目の棒グラフのmarksに以下を追加してみます。


```json
    {
      "name": "layer_1",
      "type": "rect",
      "from": {"data":"table"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "category", "offset": {"scale": "xscale", "band":0.2}},
          "width": {"scale":"xscale", "band":0.1},
          "y": {"scale": "yscale", "field": "amount"},
          "y2": {"scale": "yscale", "value": 0},
          "fill": {"value": "red"}
        }
      }
    }
```

中身は、もともとある`layer_0`と似ていますが、以下の変更がされています。

* `x`に`offset`プロパティが追加
* `width` の`band`が0.1
* `fill` のvalueが、`red`に変更

つまり、「x方向に 0.2band 分ずれて幅が0.1band分の赤色の四角を描画する」という意味になります。
実際の図はこんな感じになります。

![visualization (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51316/bf396e07-f5dd-ab3d-5117-34b1001dea76.png)
[Online Vega Editorで開く](https://vega.github.io/editor/#/gist/54fcc244e57c652c3d4d227881fcdecc/03_barchart_base.json)


Example をただ漫然と流用するのでなく、どのように描画されているかを理解すると、自分で設計して色んなグラフをかけるようにになります。


次回は [interactiveなグラフ](https://qiita.com/ihgs/items/7715bd7f6d2f7987f73a)です。