Remember in vega-lite that we could create composed plots by using concat
, hconcat
or vconcat
. Vega is more powerful to create layouts involving different plots. However, it is much more difficult/verbose to do so…
In the vega-lite tutorial, we created a double scatterplot for the cars data, that looked like this:
If we want to recreate this using vega, here is the minimal specification:
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"padding": 5,
"data": [
{
"name": "cars",
"url": "https://raw.githubusercontent.com/vega/vega/master/docs/data/cars.json",
"format": {"type": "json"}
}
],
"scales": [
{
"name": "acceleration_xscale",
"type": "linear",
"domain": {"data": "cars", "field": "Acceleration"},
"range": [0, 200],
"nice": true,
"zero": true
},
{
"name": "mpg_yscale",
"type": "linear",
"domain": {"data": "cars", "field": "Miles_per_Gallon"},
"range": [200, 0],
"nice": true,
"zero": true
},
{
"name": "horsepower_xscale",
"type": "linear",
"domain": {"data": "cars", "field": "Horsepower"},
"range": [0, 200],
"nice": true,
"zero": true
}
],
"layout": {"padding": 20},
"marks": [
{
"type": "group",
"encode": {
"update": {
"width": {"value": 200},
"height": {"value": 200}
}
},
"marks": [
{
"type": "symbol",
"style": "circle",
"from": {"data": "cars"},
"encode": {
"update": {
"x": {"scale": "acceleration_xscale", "field": "Acceleration"},
"y": {"scale": "mpg_yscale", "field": "Miles_per_Gallon"},
"fill": {"value": "steelblue"},
"fillOpacity": {"value": 0.5}
}
}
}
],
"axes": [
{
"scale": "mpg_yscale",
"orient": "left",
"gridScale": "mpg_yscale",
"grid": true,
"tickCount": 5,
"title": "Miles_per_Gallon"
},
{
"scale": "acceleration_xscale",
"orient": "bottom",
"gridScale": "acceleration_xscale",
"grid": true,
"tickCount": 5,
"title": "Acceleration"
}
]
},
{
"type": "group",
"encode": {
"update": {
"width": {"value": 200},
"height": {"value": 200}
}
},
"marks": [
{
"type": "symbol",
"style": "circle",
"from": {"data": "cars"},
"encode": {
"enter": {
"x": {"scale": "horsepower_xscale", "field": "Horsepower"},
"y": {"scale": "mpg_yscale", "field": "Miles_per_Gallon"},
"fill": {"value": "steelblue"},
"fillOpacity": {"value": 0.5}
}
}
}
],
"axes": [
{
"scale": "mpg_yscale",
"orient": "left",
"gridScale": "mpg_yscale",
"grid": true,
"tickCount": 5,
"title": "Miles_per_Gallon"
},
{
"scale": "horsepower_xscale",
"orient": "bottom",
"gridScale": "horsepower_xscale",
"grid": true,
"tickCount": 5,
"title": "Horse power"
}
]
}
]
}
For simplicity’s sake, we left out the colourScale
and legend. Still, the specification is huge: 125 lines versus what would have taken 23 lines in vega-lite.
In vega, we need to set the layout
, and the marks
itself is an array of subplots (each containing another marks
…). Each plot itself should have a "type": "group"
and in most cases the width
and height
also need to be set (otherwise any axes will be positioned wrong). Here is the relevant part:
...
"layout": {"padding": 20},
"marks": [
{
"type": "group",
"encode": {
"enter": {
"width": {"value": 200},
"height": {"value": 200}
}
},
"marks": [
{ ... },
{ ... }
],
"axes": [
{ ... },
{ ... }
]
},
{
"type": "group",
"encode": {
"enter": {
"width": {"value": 200},
"height": {"value": 200}
}
},
"marks": [
{ ... },
{ ... }
],
"axes": [
{ ... },
{ ... }
]
}
]
...
Notice that the outermost marks
is not defined as a child of layout
, but is a sibling (i.e. it stands next to layout
). Also: layout
must be defined, even if only with an empty value (i.e. "layout": {}
). If not, your plots will be put on top of each other.
Exercise - Create a multi-plot view with 3 plots instead of two, where the plots are arranged in 2 columns.