How to zoom only on a specific axis when mouse over it? - vega-lite

Starting from this concrete example where 2 plots are linked on their horizontal axis and free on their vertical axis, is there a way to zoom only on a specific axis when the mouse is over it ?
The zoom actually set is common to both axis.

If you want scrolling to be independent in each panel, you need to do two things:
set resolve.scale.x and resolve.scale.y to "independent", so the scales will not be linked.
use a different name for the bound selection in each panel, so the selectors will not be linked.
For example (vega editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {"url": "data/stocks.csv"},
"vconcat": [
{
"transform": [{"filter": "datum.symbol==='IBM'"}],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
},
"selection": {"scroll_1": {"type": "interval", "bind": "scales"}}
},
{
"transform": [{"filter": "datum.symbol==='GOOG'"}],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
},
"selection": {"scroll_2": {"type": "interval", "bind": "scales"}}
}
],
"resolve": {"scale": {"x": "independent", "y": "independent"}}
}

Related

Sort bars of Stacked Bar Chart

For a Stacked Bar Chart, can you sort the bars by the size of one of the segments?
E.g., take this Stacked Bar Chart from the examples (Open Editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"url": "data/barley.json"},
"mark": "bar",
"encoding": {
"x": {"aggregate": "sum", "field": "yield"},
"y": {"field": "variety"},
"color": {"field": "site"}
}
}
Now I would like to sort the y-axis based on the yield in Crookston. Is that possible?
Sorting by the total of another field is relatively easy; you can do so with the "sort" entry of the desired encoding (sort docs):
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"url": "data/barley.json"},
"mark": "bar",
"encoding": {
"x": {"aggregate": "sum", "field": "yield"},
"y": {"field": "variety", "sort": {"op": "sum", "field": "yield"}},
"color": {"field": "site"}
}
}
If you want to sort just by the value when site == "Crookston", you can do so by first applying a calculate transform to select just that value:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"url": "data/barley.json"},
"transform": [
{
"calculate": "datum.site == 'Crookston' ? datum.yield : 0",
"as": "crookston"
}
],
"mark": "bar",
"encoding": {
"x": {"aggregate": "sum", "field": "yield"},
"y": {"field": "variety", "sort": {"op": "sum", "field": "crookston"}},
"color": {"field": "site"}
}
}

How to position image on top left corner?

I am trying to position an overlayed image in the top left corner of my chart.
To that end, I am using the aggregate transform directly in the encoding of channels x, and y of the image, as it can be seen in this example.
Here is the specific code snippet of the image mark:
{
"mark": {"type":"image", "width":50, "align":"left"},
"encoding": {
"x": {"aggregate": "min", "field":"months", "type":"temporal"},
"y": {"aggregate": "max", "field":"price", "type":"quantitative"},
"url": {"value": "data/ffox.png"}
}
}
The image, is still appearing at around the middle of the y axis, and not at the top:
Image in the middle, not top
How can I place it at the top left corner?
The image is not getting displayed in top because height is not provided for that image mark. Because of that image is getting displayed in center, if you inspect your image you will see some default height. Image for default height
To bring your image on top left, just provide height as done below:
{
"mark": {"type": "image", "width": 50, "align": "left", "height": 40},
"encoding": {
"x": {"aggregate": "min", "field": "months", "type": "temporal"},
"y": {"aggregate": "max", "field": "price", "type": "quantitative"},
"url": {"value": "data/ffox.png"}
}
}
But with the aggregation specified, your image might slighly go outside the chart view, so you can provide the following way as well where you provide hardcoded x and y value for the image mark. Which will always show appropriate position for your image. Below is the code and editor url:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.1.0.json",
"width": "container",
"data": {"url": "data/sp500.csv"},
"transform": [{"timeUnit": "utcyearmonth", "field": "date", "as": "months"}],
"layer": [
{
"encoding": {
"x": {"field": "months", "type": "temporal", "title": null},
"y": {"field": "price", "type": "quantitative", "title": "Price"}
},
"layer": [
{
"mark": {
"type": "area",
"color": "#3873b9",
"fillOpacity": 0.7,
"tooltip": true
}
},
{"mark": {"type": "line", "color": "#4883c9"}}
]
},
{
"mark": {"type": "image", "width": 50, "height": 40, "align": "left"},
"encoding": {
"x": {
"datum": 0,
"type": "quantitative",
"scale": {"domain": [0, 1]},
"axis": null
},
"y": {
"datum": 0.8,
"type": "quantitative",
"scale": {"domain": [0, 1]},
"axis": null
},
"url": {"value": "data/ffox.png"}
}
}
],
"resolve": {
"axis": {"x": "independent", "y": "independent"},
"scale": {"x": "independent", "y": "independent"}
}
}
As wahab memon mentioned, the image went middle due to the missing of height property.
Simply adding back "height": 50, "baseline": "alphabetic" to mark can fix the position and the overshoot issue as well. (no need for hard coding)
Last but not least, the original code has redundant nested layers, please see the complete code below:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.1.0.json",
"width": "container",
"data": {"url": "data/sp500.csv"},
"transform": [{"timeUnit": "utcyearmonth", "field": "date", "as": "months"}],
"encoding": {
"x": {"field": "months", "type": "temporal", "title": null},
"y": {"field": "price", "type": "quantitative", "title": "Price"}
},
"layer": [
{
"mark": {
"type": "area",
"color": "#3873b9",
"fillOpacity": 0.7,
"tooltip": true
}
},
{"mark": {"type": "line", "color": "#4883c9"}},
{
"mark": {"type": "image", "width": 50, "align": "left", "height": 50, "baseline": "alphabetic"},
"encoding": {
"x": {"aggregate": "min", "field": "months", "type": "temporal"},
"y": {"aggregate": "max", "field": "price", "type": "quantitative"},
"url": {"value": "data/ffox.png"}
}
}
]
}
Vega Editor

How to link multiple plots with vega-lite only on horizontal axis?

I have tested this:
https://vega.github.io/editor/?#/url/vega-lite/N4IgJAzgxgFgpgWwIYgFwhgF0wBwqgegIDc4BzJAOjIEtMYBXAI0poHsDp5kTykBaADZ04JACyUAVhDYA7EABoQAEySYUqUAwBOgtCrVJOmNlADWESlAjEQAXyXEocqGrQBtUJm1JZEAGZs2ggeoP40gphw2vqqmAwIlBAAnghMbIIAvNkA5ACSAEIAsjn2ALpKyNpm+sKycIogcLLOyjSyZGigAB5dIOFwgsqxag1KmMk4DehRCDhBSHoOIMl9A0P6ONo0UGMgE1P6AI4Mvph0ajSk9ssQg3BQ53J92uTs8pr7k9Mg7VHaxEWjSY7WG6GgizgEBuDi8Pj8gWCoX6EX+I3iiRSaQy2UyOQA4gB5Qn40p2CogKo1dB1PbNVrtTqfXqfdZggxRRoHH6zeY+JZKVasmiDdlbHZ7bnHU6yc7qc7XOy3e6Pd4vN7PT5S9B-aKAvRKEGydkQwRQmEU14yQTXT6m6Y9fQQGBIV7DJV2IA
But without success since the vertical axis is also linked.
Is there also a way to limit wheel zoom to one axis only ?
You can limit the scale binding to a single axis by specifying the "encodings" property of the selection. For example, this binds the selection only to the x-axis (view in vega editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {"url": "data/stocks.csv"},
"vconcat": [
{
"transform": [{"filter": "datum.symbol==='IBM'"}],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
},
"selection": {
"region": {"type": "interval", "bind": "scales", "encodings": ["x"]}
}
},
{
"transform": [{"filter": "datum.symbol==='GOOG'"}],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
},
"selection": {
"region": {"type": "interval", "bind": "scales", "encodings": ["x"]}
}
}
],
"resolve": {"scale": {"x": "shared", "y": "independent"}}
}
If you want independent y scale binding in each chart, with a shared x-binding, you can do this by adding a new independent bound selection in each chart (vega editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {"url": "data/stocks.csv"},
"vconcat": [
{
"transform": [{"filter": "datum.symbol==='IBM'"}],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
},
"selection": {
"y_scroll_1": {"type": "interval", "bind": "scales", "encodings": ["y"]},
"x_scroll": {"type": "interval", "bind": "scales", "encodings": ["x"]}
}
},
{
"transform": [{"filter": "datum.symbol==='GOOG'"}],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
},
"selection": {
"y_scroll_2": {"type": "interval", "bind": "scales", "encodings": ["y"]},
"x_scroll": {"type": "interval", "bind": "scales", "encodings": ["x"]}
}
}
],
"resolve": {"scale": {"x": "shared", "y": "independent"}}
}

Vega-Lite layered chart: how to get tick marks and tick labels to span the entire axis?

I am working on a layered chart where I have both bars and rule lines. The issue I'm having is that on the x-axis, the tick marks and tick labels only appear under the bars and do not span the entire axis, making it so that there are no tick marks and labels underneath where the rule lines are located. Here is an example of what I'm seeing (link to Vega editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {"url": "data/movies.json"},
"transform": [
{"calculate": "2*datum.IMDB_Rating", "as": "UpperLimit"}
],
"layer": [
{
"mark": "bar",
"encoding": {
"x": {"bin": true, "field": "IMDB_Rating", "type": "quantitative"},
"y": {"aggregate": "count", "type": "quantitative"}
}
},
{
"mark": "rule",
"encoding": {
"x": {
"aggregate": "max",
"field": "UpperLimit",
"type": "quantitative"
},
"color": {"value": "red"},
"size": {"value": 5}
}
}
]
}
Image of issue
How do I get the tick marks and labels to span the entire axis? Thanks in advance for the help!
When you use a bin transform within an encoding, Vega-Lite adjusts the default axis properties to match the binning. You can re-adjust these manually via the encoding's scale and axis properties, but I think a simpler way is to move the bin transform to the chart's transform specification. Here is an example (Vega Editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {"url": "data/movies.json"},
"transform": [
{"calculate": "2*datum.IMDB_Rating", "as": "UpperLimit"},
{
"bin": true,
"field": "IMDB_Rating",
"as": ["IMDB_Rating_0", "IMDB_Rating_1"]
}
],
"layer": [
{
"mark": "bar",
"encoding": {
"x": {
"field": "IMDB_Rating_0",
"type": "quantitative",
"bin": "binned"
},
"x2": {"field": "IMDB_Rating_1"},
"y": {"aggregate": "count", "type": "quantitative"}
}
},
{
"mark": "rule",
"encoding": {
"x": {
"aggregate": "max",
"field": "UpperLimit",
"type": "quantitative"
},
"color": {"value": "red"},
"size": {"value": 5}
}
}
]
}

Is there a way to add a line break between the plot and X axis (vega-lite)

I am not sure if it makes sense but will it be possible to add a line break between the start of the plot and the X-axis.
For e.g.
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"width": {"step": 10},
"height": 120,
"data": {"url": "data/cars.json"},
"mark": "area",
"encoding": {
"x": {"field": "Name", "type": "nominal", "scale": {"round": false}},
"y": {"aggregate": "count", "type": "quantitative"}
}
}
Hopeful output:
One way to do this is by adding a scale.domain argument:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"width": {"step": 10},
"height": 120,
"data": {"url": "data/cars.json"},
"mark": "area",
"encoding": {
"x": {"field": "Name", "type": "nominal", "scale": {"round": false}},
"y": {"aggregate": "count", "type": "quantitative", "scale": {"domain": [-0.5, 6]}}
}
}
Another way to do this is to use the y and y2 encodings to set a bottom value for the area chart:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"width": {"step": 10},
"height": 120,
"data": {"url": "data/cars.json"},
"mark": "area",
"transform": [{"calculate": "0.1", "as": "bottom"}],
"encoding": {
"x": {"field": "Name", "type": "nominal", "scale": {"round": false}},
"y": {"aggregate": "count", "type": "quantitative"},
"y2": {"field": "bottom"}
}
}
Another way to do something similar, adding it as another answer to make it convenient for others.
offset property of axis shifts the axis line by fixed pixels, independent of the data. Using offset adds a gap between the x and y axis lines though.
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"width": {"step": 10},
"height": 120,
"data": {"url": "data/cars.json"},
"mark": "area",
"encoding": {
"x": {"field": "Name", "type": "nominal", "scale": {"round": false}, "axis": {"offset": 5}},
"y": {"aggregate": "count", "type": "quantitative"}
}
}