简体   繁体   中英

Share data between vega-lite graphs

I have a site with two vega-lite graphs that show different aspects of the same dataset, which is generated dynamically (similar to this example). Currently they both hold their own version of this dataset.

Since the dataset tends to get quite big I would like them to share the data between them so they use less memory.

Since the data will be updated later (from the function update_vega() ) I can't just put it into a variable and embed it in both diagrams.

Is it possible in vega-lite to have multiple graphs sharing the same data-object and how can I do it?

Here is my code (I have only been learning javascript 3 days ago, so I am very happy about feedback on every level):

<!DOCTYPE html>
<html>
<body>
<!-- setup of the vega graph -->
<script src="https://cdn.jsdelivr.net/npm/vega@5.10.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite@4.6.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6.3.2"></script>
<div id="vega_graph_one"></div>
<div id="vega_graph_two"></div>
<script>
  var vlSpec_one = {
      $schema: 'https://vega.github.io/schema/vega-lite/v4.json',
      data: { name: 'table', values: [{"time":11, "age": 4},{"time":12, "age": 4},{"time":11, "age": 5}]},
      width: 400,
      mark: 'bar',
      encoding: {
          x: {field: 'time', type: 'quantitative', binned: true},
          y: {aggregate: "count", type: 'quantitative'},
          color: {field: 'age', type: 'quantitative'}
      }
  }
  var vlSpec_two = {
      $schema: 'https://vega.github.io/schema/vega-lite/v4.json',
      data: { name: 'table', values: [{"time":11, "age": 4},{"time":12, "age": 4},{"time":11, "age": 5}]},
      width: 400,
      mark: 'point',
      encoding: {
          x: {field: 'time', type: 'quantitative'},
          y: {field: 'age', type: 'quantitative'},
      }
  }
  // two global variables so the view can be updated from an outside function
  var view_one;
  var view_two;
  vegaEmbed('#vega_graph_one', vlSpec_one).then(
      result => { view_one = result.view;},
      reason => { console.error(reason);}
  )
  vegaEmbed('#vega_graph_two', vlSpec_two).then(
      result => { view_two = result.view;},
      reason => { console.error(reason);}
  )

  // update the vega graph from outside

  // call with update_vega([{"time":11, "age": 4},{"time":12, "age": 4},{"time":9, "age": 6}])
  function update_vega(event_data){
      var changeSet = vega.changeset()
          .insert(
              event_data
          );
      // data dublication happense here
      view_one.change("table", changeSet).run();
      view_two.change("table", changeSet).run();
  }
</script>
</body>
</html>

First, consider putting your data in javascript function and call it in data, should be easier to maintain for both data and chart:

function getData(){
 var mydata = [{"time":11,"age": 4},{"time":12,"age": 4},{"time":11, "age":5}];

return mydata;
}

Then you can call it:

{
  "data": getData(),
  "mark": {"type" : "bar"}
}

There are several concepts that help achieving data sharing based on your needs. You need just one vegaEmbed and one vlSpec that utilizes one of the following:

Layers

Put data on top of all layers and refer to it from each mark's layer

{
  "data": {"values":getData()},
  "layer": [
   {
     "mark": {"type" : "bar"}
   },
   {
     "mark": {"type" : "point"}
   }
 ]
}

Concat

vconcat , hconcat , and concat can be used to produce multiple charts of different mark each using same data, it doesn't perfectly suite your case because you don't have the same x and y fields in every mark . Read more on Concatenating views

{
  "data": {"values":getData()},
  "concat": [
   {
     "mark": {"type" : "line"},
     "encoding": {
       "x": {"field": "time"},
       "y": {"field": "age"}
     }
   },
   {
     "mark": {"type" : "bar"},
     "encoding": {
       "x": {"field": "time"},
       "y": {"field": "age"}
     }
   }
 ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM