Kibana 6.2.0リリース記念　Vegaで誤差棒（ErrorBarにチャレンジジョイ

# 概要

Vegaの記法でKibanaのVisualizationをやりくりするのって、まだ慣れませんね。
6.2.0では、Vegaが使えるようになったということで、ぐっと可視化力があがったと思います。

以前は、こんな質問がElasticのフォーラムに上がっていました。

* [誤差棒について](https://discuss.elastic.co/t/topic/87211/3)

> ![誤差棒について   Elastic In Your Native Tongue   日本語による質問・議論はこちら   Discuss the Elastic Stack.png](https://qiita-image-store.s3.amazonaws.com/0/111676/481c348d-f1dd-754d-aa0e-2e0a883b479f.png)


当時はうまい解決策が見つからなかったようですが、今ならVegaでやれそうだ、ということでやってみた。

# 先に結論

![a   Kibana.png](https://qiita-image-store.s3.amazonaws.com/0/111676/3572571a-6389-17c7-a092-a79e1fde8204.png)

# データの準備

データについては、気象庁の「[過去の気象データ・ダウンロード](http://www.data.jma.go.jp/gmd/risk/obsdl/index.php)」からCSVを頂戴します。
1年分の東京の平均気温のCSVをダウンロードしました。

これをElasticsearchに入れて、検索するとこう見えます。

|field|説明|
|----|----|
|temp_value| 平均気温 |
|timestamp | 時系列の元となるDate値 |


```json
     {
        "_index": "doc",
        "_type": "weather",
        "_id": "0",
        "_score": 1,
        "_source": {
          "temp_value": 5.6,
          "timestamp": "2017-02-07T00:00:00"
        }
      },
      {
        "_index": "doc",
        "_type": "weather",
        "_id": "14",
        "_score": 1,
        "_source": {
          "temp_value": 6.1,
          "timestamp": "2017-02-21T00:00:00"
        }
      },
      {
        "_index": "doc",
        "_type": "weather",
        "_id": "19",
        "_score": 1,
        "_source": {
          "temp_value": 8.6,
          "timestamp": "2017-02-26T00:00:00"
        }
      }

```


# Vegaの記述

今回は、３つのグラフを重ね合わせます。

|No|グラフ| 用途|
|----|-----|-------|
| 1 | point | 平均気温を丸でプロットする |
| 2 | line  | 各月の平均気温を線で結ぶ |
| 3 | rule  | 誤差棒相当の縦線を描画する |

## データ取得部分

```json
"data": {
    "url": {
      "%context%": true,
      "%timefield%": "timestamp",
      "index": "doc",
      "body": {
        "aggs": {
          "time_buckets": {
            "date_histogram": {
              "field": "timestamp",
              "interval": "1M",
              "extended_bounds": {
                "min": {"%timefilter%": "min"},
                "max": {"%timefilter%": "max"}
              },
              "min_doc_count": 0
            },
            "aggs": {"avg_temp": {"avg": {"field": "temp_value"}}}
          }
        },
        "size": 0
      }
    },
    "format": {"property": "aggregations.time_buckets.buckets"}
  }
```

各月の平均気温を求めるので、月単位のAggregationの下にAverageのAggregationを追加する形となります。

> "aggs" : { "avg_temp": ... }

とした、avg_tempは後で使うので、しっかり覚えておきます。

## 誤差棒部分のデータを作る

今回は平均気温しかIndexしていないので、上下の誤差の値がありません。
適当に下に-1、上に+2とする例を示します。transformの部分に注目してください。

```json
"transform": [
    {"calculate": "datum.avg_temp.value-1", "as": "lower"},
    {"calculate": "datum.avg_temp.value+2", "as": "upper"}
  ],
```

**datum.avg_temp.value**とすることで、上のdataで取得したavg_tempのAggregation結果にアクセスできます。
**as**で、名前を付けて保存します。lowerとupperとしていますが、これも後で使います。

## Layer

上で取得したdata、加工したデータをもとに、いよいよグラフを書いていくところです。
Layerで複数のグラフを重ねていくわけですが、順に見ていきます。

### point

|項目|値|説明|
|----|---|---|
| type | point | ポイントをプロットするタイプを宣言する |
| filled | true or false | trueにしておくと●、falseにしておくと○ |
| size | 100 | 円の大きさを指定する |

date_histogramで取得した時系列の値はkey, "timeUnit": "yearmonthdate"でx軸に描画できます。
y軸の値は、先に宣言していたavg_temp.valueを使用します。

```json
 {
      "mark": {"type": "point", "filled": false, "size": 100},
      "encoding": {
        "x": {
          "field": "key",
          "timeUnit": "yearmonthdate",
          "scale": {"zero": false},
          "axis": {"title": "年月"}
        },
        "y": {"field": "avg_temp.value"},
        "color": {"value": "black"}
      }
    },
```
### line

先のpointと違うのは、typeがlineになったこと、colorがredになったぐらいで特に変わりはありません。

```json
{
      "mark": {"type": "line"},
      "encoding": {
        "x": {
          "field": "key",
          "timeUnit": "yearmonthdate",
          "scale": {"zero": false},
          "axis": {"title": "年月"}
        },
        "y": {"field": "avg_temp.value"},
        "color": {"value": "red"}
      }
    }
```

### rule

いよいよ誤差棒的なグラフを書きます。
pointやlineとx軸の設定部分については同じですが、yのところが違います。

これまで、yは１つの指定でしたが、y2の指定もすることになります。これで縦線が引けるということですね。

| 項目 | 値 | 説明 |
|----|----|-----|
| y.field | upper | trasformで計算して取得した avg_tempの値に**+2**した数値 |
| y2.field | lower | trasformで計算して取得した avg_tempの値に**-1**した数値 |


```json
 {
      "mark": "rule",
      "encoding": {
        "x": {
          "field": "key",
          "timeUnit": "yearmonthdate",
          "axis": {"title": "年月"}
        },
        "y": {"field": "upper", "type": "quantitative"},
        "y2": {"field": "lower", "type": "quantitative"}
      }
    }
```

# 最後に

今回は固定値でプラスマイナスしていますが、標準偏差から求めるなり、適当に値をセットしてやれば誤差棒は描けると思います。
なお、使用したものは、[こちら](https://gist.github.com/tsgkdt/df8832dd2057986648ddfe87db4d3bd0)にあげておきます。


Vegaにはほかにもいろいろな見せ方があるので、おいおい試していきたいですね！