LoginSignup
1
3

More than 3 years have passed since last update.

Vega 学習 その2

Last updated at Posted at 2019-05-19

前回は以下

Vega 学習 その1

散布図

このExample の場合、dataは外部から取得しています("url": "data/cars.json")。
dataの中身は、ここで確認できます。

データ投入

Elasticsearch へのデータ投入は、今回は[Machine Learning]-[Data Visualizer]-[Import Data]を利用しました。
ただし、Importするには、Json ではなくNewline-delimited JSONである必要があるので、以下のスクリプトで変換。
https://gist.github.com/ihgs/caf192943889607afe3c4175fd776917

cat cars.json | python json2ndjson.py > cars.ndjson

Vega HJSON

{
  $schema: https://vega.github.io/schema/vega/v3.3.1.json
  width: 200
  height: 200
  padding: 5
  data: [
    {
      name: source
      url: {  // imoprt したデータのindexを指定
        index: vega_example_cars
        body: {size: 1000}
      }
      format: {property: "hits.hits"}
      transform: [
        {
          type: filter
          expr: datum['_source'].Horsepower != null && datum['_source'].Miles_per_Gallon != null && datum['_source'].Acceleration != null
        }
      ]
    }
  ]
  scales: [
    {
      name: x
      type: linear
      round: true
      nice: true
      zero: true
      domain: {data: "source", field: "_source.Horsepower"}
      range: width
    }
    {
      name: y
      type: linear
      round: true
      nice: true
      zero: true
      domain: {data: "source", field: "_source.Miles_per_Gallon"}
      range: height
    }
    {
      name: size
      type: linear
      round: true
      nice: false
      zero: true
      domain: {data: "source", field: "_source.Acceleration"}
      range: [4, 361]
    }
  ]
  axes: [
    {
      scale: x
      grid: true
      domain: false
      orient: bottom
      tickCount: 5
      title: Horsepower
    }
    {
      scale: y
      grid: true
      domain: false
      orient: left
      titlePadding: 5
      title: Miles_per_Gallon
    }
  ]
  legends: [
    {
      size: size
      title: Acceleration
      format: s
      symbolStrokeColor: "#4682b4"
      symbolStrokeWidth: 2
      symbolOpacity: 0.5
      symbolType: circle
    }
  ]
  marks: [
    {
      name: marks
      type: symbol
      from: {data: "source"}
      encode: {
        update: {
          x: {scale: "x", field: "_source.Horsepower"}
          y: {scale: "y", field: "_source.Miles_per_Gallon"}
          size: {scale: "size", field: "_source.Acceleration"}
          shape: {value: "circle"}
          strokeWidth: {value: 2}
          opacity: {value: 0.5}
          stroke: {value: "#4682b4"}
          fill: {value: "transparent"}
        }
      }
    }
  ]
}

メモ

  • transform: filterを使い欠損データを除外
  • marks: type にsymbolを指定。

ネットワーク図

データ投入

上と同様に、[Machine Learning]-[Data Visualizer]-[Import Data]を利用。
今回のデータは、{"nodes": ..., "links": ...}といった構造になっており、vegaで描画する際は、nodes, links を別々に扱っているので、それぞれindexをわけてImport してみます。
投入データは同様にスクリプトで変換しておきます。

cat miserables.json | python json2ndjson.py --key nodes > nodes.ndjson
cat miserables.json | python json2ndjson.py --key links > links.ndjson

Vega HJSON

{
  $schema: https://vega.github.io/schema/vega/v3.3.1.json
  width: 700
  height: 500
  padding: 0
  autosize: none
  signals: [
    {name: "cx", update: "width / 2"}
    {name: "cy", update: "height / 2"}
    {
      name: nodeRadius
      value: 8
      bind: {input: "range", min: 1, max: 50, step: 1}
    }
    {
      name: nodeCharge
      value: -30
      bind: {input: "range", min: -100, max: 10, step: 1}
    }
    {
      name: linkDistance
      value: 30
      bind: {input: "range", min: 5, max: 100, step: 1}
    }
    {
      name: static
      value: true
      bind: {input: "checkbox"}
    }
    {
      description: State variable for active node fix status.
      name: fix
      value: false
      on: [
        {
          events: symbol:mouseout[!event.buttons], window:mouseup
          update: "false"
        }
        {events: "symbol:mouseover", update: "fix || true"}
        {
          events: "[symbol:mousedown, window:mouseup] > window:mousemove!"
          update: xy()
          force: true
        }
      ]
    }
    {
      description: Graph node most recently interacted with.
      name: node
      value: null
      on: [
        {
          events: symbol:mouseover
          update: fix === true ? item() : node
        }
      ]
    }
    {
      description: Flag to restart Force simulation upon data changes.
      name: restart
      value: false
      on: [
        {
          events: {signal: "fix"}
          update: fix && fix.length
        }
      ]
    }
  ]
  data: [
    //修正
    {
      name: node-data
      url: {index: "test_vega_tree_nodes", size: 1000}
      format: {type: "json", property: "hits.hits"}
    }
    {
      name: link-data
      url: {index: "test_vega_tree_links", size: 1000}
      format: {type: "json", property: "hits.hits"}
      transform: [
        {
          type: formula
          expr: datum['_source'].source
          as: source
        }
        {
          type: formula
          expr: datum['_source'].target
          as: target
        }
        {type: "formula", expr: "datum['_source'].value", as: "value"}
      ]
    }
  ]
  scales: [
    {
      name: color
      type: ordinal
      domain: {data: "node-data", field: "_source.group"}
      range: {scheme: "category20c"}
    }
  ]
  marks: [
    {
      name: nodes
      type: symbol
      zindex: 1
      from: {data: "node-data"}
      on: [
        {
          trigger: fix
          modify: node
          values: fix === true ? {fx: node.x, fy:node.y} : {fx: fix[0], fy: fix[1]}
        }
        {
          trigger: !fix
          modify: node
          values: "{fx: null, fy: null}"
        }
      ]
      encode: {
        enter: {
          fill: {scale: "color", field: "_source.group"}
          stroke: {value: "white"}
        }
        update: {
          size: {signal: "2 * nodeRadius * nodeRadius"}
          cursor: {value: "pointer"}
        }
      }
      transform: [
        {
          type: force
          iterations: 300
          restart: {signal: "restart"}
          static: {signal: "static"}
          signal: force
          forces: [
            {
              force: center
              x: {signal: "cx"}
              y: {signal: "cy"}
            }
            {
              force: collide
              radius: {signal: "nodeRadius"}
            }
            {
              force: nbody
              strength: {signal: "nodeCharge"}
            }
            {
              force: link
              links: link-data
              distance: {signal: "linkDistance"}
            }
          ]
        }
      ]
    }
    {
      type: path
      from: {data: "link-data"}
      interactive: false
      encode: {
        update: {
          stroke: {value: "#ccc"}
          strokeWidth: {value: 0.5}
        }
      }
      transform: [
        {
          type: linkpath
          require: {signal: "force"}
          shape: line
          sourceX: datum.source.x
          sourceY: datum.source.y
          targetX: datum.target.x
          targetY: datum.target.y
        }
      ]
    }
  ]
}

メモ

  • data: node,linkをそれぞれで取得。
  • marks内のtransform のtype:force, force:link linkのデータをきちんと値を渡せるようにするため、source とtarget を設定するように変換を実施。なお、一番下のtype:linkpath で使っているdatum.source.xとかは、force:link で変換されたものを利用。

まとめ

ファイルからデータを投入できる[Machine Learning]-[Data Visualizer]-[Import Data]は便利。
次回は、kibanaとより連携する部分を調べていこうと思います。 vega そのものについて解説していく記事を優先することにしました。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3