vega won't update until the mouse has brushed over the div containing the chart - vega

I ran into a subtle vega update behavior that I hope to get your help on
--- when I use the view API to update the signal for a visual element (e.g., a brush), the UI doesn't appear to update until I move my mouse over to the div --- in the notebook, this can create a jarring experience. Is there any way to "eagerly" perform the update?
You can run the following JSON and run the script below in the console
to reproduce the effect that I am talking about. Thanks!
Have the following spec in Vega Editor
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Midas Generated Visualization of dataframe STATE_distribution",
"selection": {
"zoom": {
"type": "interval",
"bind": "scales",
"translate": "[mousedown[!event.shiftKey], window:mouseup] > window:mousemove!",
"zoom": "wheel!"
},
"brush": {
"type": "interval",
"resolve": "union",
"on": "[mousedown[event.shiftKey], window:mouseup] > window:mousemove!",
"translate": "[mousedown[event.shiftKey], window:mouseup] > window:mousemove!",
"zoom": null,
"encodings": ["x"]
}
},
"data": {
"values": [
{"STATE": "AK", "count": 2, "is_overview": true},
{"STATE": "RI", "count": 4, "is_overview": true},
{"STATE": "WA", "count": 75, "is_overview": true},
{"STATE": "WI", "count": 120, "is_overview": true},
{"STATE": "WV", "count": 155, "is_overview": true},
{"STATE": "WY", "count": 43, "is_overview": true}
]
},
"mark": "bar",
"encoding": {
"x": {"field": "STATE", "type": "ordinal"},
"y": {"field": "count", "type": "quantitative", "stack": null},
"color": {
"field": "is_overview",
"type": "nominal",
"scale": {"range": ["#003E6B", "#9FB3C8"], "domain": [false, true]},
"legend": null
},
"opacity": {"value": 0.5}
},
"config": {}
}
Then paste VEGA_DEBUG.view.signal("brush_x", [10, 100]) in the console. You will see that the brush will not update until you move your mouse over to the div that contains the chart.

After updating a signal, call runAsync() to invoke an update. The behavior that you see where the view updates when you hover over it comes from the fact that Vega listens to hover events and invokes an updates.

Related

How to display multiple charts with varying x-scales side by side in Vega

I have a set of charts with the same y-scale but varying x-scales. I am using hconcat to display them side by side. In order to conserve space and avoid repetition, I have disabled the y-axis for all but the first chart. However, this is causing the title of the first chart to offset:
This is a link to a Vega Editor.
As the blue circle indicates, the two titles, "Chain" and "Mini Invaders," are not in line. Is there a way to fix this?
I have tried to express these charts using facet but as far as I can tell, facets do not permit varying x-scales. However, please do let me know if this is somehow possible with facets.
You need labelBound: true in your spec.
Editor
{
"config": {
"view": {
"continuousWidth": 400,
"continuousHeight": 300,
"stroke": "#000000",
"strokeOpacity": 1,
"strokeWidth": 2
},
"axis": {"labelFontSize": 24, "titleFontSize": 24, "labelBound":true},
"legend": {"labelFontSize": 24, "labelLimit": 0, "titleFontSize": 32},
"title": {"baseline": "bottom", "fontSize": 24}
},
"hconcat": [
{
"layer": [
{
"mark": {"type": "area", "clip": true, "opacity": 0.2},
"encoding": {
"color": {
"field": "Variations",
"legend": {
"orient": "top",
"symbolOpacity": 1,
"symbolSize": 200,
"symbolStrokeWidth": 3,
"symbolType": "stroke"
},
"scale": {
"domain": ["Original Algorithm"],
"range": [
"#e41a1c",
"#377eb8",
"#4daf4a",
"#984ea3",
"#a65628",
"#646464"
]
},
"type": "nominal"
},
"x": {"field": "step", "type": "quantitative"},
"y": {
"axis": {"labels": true, "tickCount": 5, "title": null},
"field": "lower",
"type": "quantitative"
},
"y2": {"field": "upper"}
}
},
{
"mark": {"type": "line", "clip": true},
"encoding": {
"color": {"field": "Variations", "type": "nominal"},
"x": {"field": "step", "type": "quantitative"},
"y": {
"field": "regret",
"scale": {"domain": [0, 1]},
"type": "quantitative"
}
}
}
],
"height": 200,
"title": "Chain",
"transform": [{"filter": "(datum.domain === 'Chain')"}],
"width": 200
},
{
"layer": [
{
"mark": {"type": "area", "clip": true, "opacity": 0.2},
"encoding": {
"color": {
"field": "Variations",
"legend": {
"orient": "top",
"symbolOpacity": 1,
"symbolSize": 200,
"symbolStrokeWidth": 3,
"symbolType": "stroke"
},
"scale": {
"domain": ["Original Algorithm"],
"range": [
"#e41a1c",
"#377eb8",
"#4daf4a",
"#984ea3",
"#a65628",
"#646464"
]
},
"type": "nominal"
},
"x": {"field": "step", "type": "quantitative"},
"y": {
"axis": {"labels": false, "tickCount": 5, "title": null},
"field": "lower",
"type": "quantitative"
},
"y2": {"field": "upper"}
}
},
{
"mark": {"type": "line", "clip": true},
"encoding": {
"color": {"field": "Variations", "type": "nominal"},
"x": {"field": "step", "type": "quantitative"},
"y": {
"field": "regret",
"scale": {"domain": [0, 1]},
"type": "quantitative"
}
}
}
],
"height": 200,
"title": "Mini Invaders",
"transform": [{"filter": "(datum.domain === 'Mini Invaders')"}],
"width": 200
}

How would I add a tooltip to a multi series line chart

I'm new to WebStorm and vega/vegalite and I am working on creating a visual with different types of gasoline and their prices from 1996-2020.
I've been able to create a graph with all of the information, but it's pretty hard to discern anything.
I've been going over the Vega-Lite documentation and I see that that I can use tooltips to zoom into the graphic. I tried implementing it, but I don't think I quite understand the scope of some of the properties.
Could someone show me how they might approach this task? Or perhaps even recommend videos or websites that might help me better understand how to do?
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Area charts of stock prices, with an interactive overview and filtered detail views.",
"width": 720,
"height": 480,
"padding": 5,
"data": {
"name": "gas_prices",
"url": "data/testInfo.csv",
"format": {"type": "csv", "parse": {"A1": "number", "date": "date"}}
},
"repeat": {
"layer": ["A1","A2","A3","R1","R2","R3","M1","M2","M3","P1","P2","P3","D1"]
},
"spec": {
"mark": "line",
"encoding": {
"x": {
"timeUnit": "yearmonth",
"title": "Date",
"field": "date"
},
"y": {
"field": {"repeat":"layer"},
"title": "Gas Prices",
"type": "quantitative"
},
"color": {
"datum": {"repeat": "layer"},
"type": "nominal"
}
}
}
}
You can refer the documentation for tooltip, which says about the options available to enable tooltips on your chart.
Below is a sample config having default tooltip or refer editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"repeat": ["Horsepower", "Miles_per_Gallon", "Acceleration", "Displacement"],
"columns": 2,
"spec": {
"data": {"url": "data/cars.json"},
"mark": {"type": "bar", "tooltip": true},
"encoding": {
"x": {"field": {"repeat": "repeat"}, "bin": true},
"y": {"aggregate": "count"},
"color": {"field": "Origin"}
}
}
}
To have tooltips with some customizations, you can refer below code or editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"repeat": ["Horsepower", "Miles_per_Gallon", "Acceleration", "Displacement"],
"columns": 2,
"spec": {
"data": {"url": "data/cars.json"},
"mark": "bar",
"encoding": {
"tooltip": [
{"aggregate": "count", "title": "YAxis"},
{"field": {"repeat": "repeat"}, "title": "myXAxis"}
],
"x": {"field": {"repeat": "repeat"}, "bin": true},
"y": {"aggregate": "count"},
"color": {"field": "Origin"}
}
}
}

Vega-Lite: How to use slider value in transform calculation

How do I use the value of a slider in the transform?
This example from vega online editor plots a sine and cosine wave.
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Plots two functions using a generated sequence.",
"width": 300,
"height": 150,
"data": {
"sequence": {
"start": 0,
"stop": 12.7,
"step": 0.1,
"as": "x"
}
},
"transform": [
{
"calculate": "sin(datum.x)",
"as": "sin(x)"
},
{
"calculate": "cos(datum.x)",
"as": "cos(x)"
},
{
"fold": ["sin(x)", "cos(x)"]
}
],
"mark": "line",
"encoding": {
"x": {
"type": "quantitative",
"field": "x"
},
"y": {
"field": "value",
"type": "quantitative"
},
"color": {
"field": "key",
"type": "nominal",
"title": null
}
}
}
I would like to add two sliders and use their values in the calculation. I can define sliders using:
"selection" : {
"amp" : {
"type" : "single",
"fields" : ["sin", "cos"],
"bind": {
"sin": { "input" : "range", "min": 0.0, "max": 10.0, "step": 0.1},
"cos": { "input" : "range", "min": 0.0, "max": 10.0, "step": 0.1}
}
}
},
How do I access the slider values to use in the calculations? Something like
{
"calculate": "amp.sin * sin(datum.x)",
"as": "sin(x)"
},
You can do this in exactly the way you wrote in your question. Additionally, adding an initial value will make the selections valid before you interact with them.
Here is a full example (vega editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Plots two functions using a generated sequence.",
"width": 300,
"height": 150,
"data": {"sequence": {"start": 0, "stop": 12.7, "step": 0.1, "as": "x"}},
"transform": [
{"calculate": "amp.sin * sin(datum.x)", "as": "sin(x)"},
{"calculate": "amp.cos * cos(datum.x)", "as": "cos(x)"},
{"fold": ["sin(x)", "cos(x)"]}
],
"mark": "line",
"encoding": {
"x": {"type": "quantitative", "field": "x"},
"y": {"field": "value", "type": "quantitative"},
"color": {"field": "key", "type": "nominal", "title": null}
},
"selection": {
"amp": {
"type": "single",
"fields": ["sin", "cos"],
"init": {"sin": 1, "cos": 1},
"bind": {
"sin": {"input": "range", "min": 0, "max": 10, "step": 0.1},
"cos": {"input": "range", "min": 0, "max": 10, "step": 0.1}
}
}
}
}

Vega-lite set color from data whilst retaining a legend

I'm trying to use values from the data in order to set the colors of the bars. I would also like this to be reflected in a legend.
So I've figured out how to use a specific color for a bar, based on a value in the data:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A bar chart that directly encodes color names in the data.",
"data": {
"values": [
{
"color": "rgb(0, 0, 0)",
"b": 28,
"type": "outside"
},
{
"color": "rgb(255, 0, 0)",
"b": 55,
"type": "inside"
},
{
"color": "rgb(0, 255, 0)",
"b": 43,
"type": "dew"
}
]
},
"mark": "bar",
"encoding": {
"x": {
"field": "type",
"type": "nominal"
},
"y": {
"field": "b",
"type": "quantitative"
},
"color": { "field": "color", "type": "nominal", "legend": {}, "scale": null}
}
}
Correctly colored bars:
The above only works due to the "scale": null which prevents the legend from showing. If I remove this, then the legend shows, but the custom colors are lost and I get the rbg values showing up in the legend:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A bar chart that directly encodes color names in the data.",
"data": {
"values": [
{
"color": "rgb(0, 0, 0)",
"b": 28,
"type": "outside"
},
{
"color": "rgb(255, 0, 0)",
"b": 55,
"type": "inside"
},
{
"color": "rgb(0, 255, 0)",
"b": 43,
"type": "dew"
}
]
},
"mark": "bar",
"encoding": {
"x": {
"field": "type",
"type": "nominal"
},
"y": {
"field": "b",
"type": "quantitative"
},
"color": { "field": "color", "type": "nominal", "legend": {}}
}
}
Colors lost, wrong legend labels:
I can obviously get the correct legend labels with:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A bar chart that directly encodes color names in the data.",
"data": {
"values": [
{
"color": "rgb(0, 0, 0)",
"b": 28,
"type": "outside"
},
{
"color": "rgb(255, 0, 0)",
"b": 55,
"type": "inside"
},
{
"color": "rgb(0, 255, 0)",
"b": 43,
"type": "dew"
}
]
},
"mark": "bar",
"encoding": {
"x": {
"field": "type",
"type": "nominal"
},
"y": {
"field": "b",
"type": "quantitative"
},
"color": { "field": "type", "type": "nominal", "legend": {}}
}
}
But still I don't get the colors I want:
Is it possible to have both custom colors and a legend?
The way to get custom colors to appear in a legend is to use a scale with a custom scheme. For example, you could create the chart you have in mind this way:
(view in vega editor)
{
"data": {
"values": [
{"b": 28, "type": "outside"},
{"b": 55, "type": "inside"},
{"b": 43, "type": "dew"}
]
},
"mark": "bar",
"encoding": {
"x": {"field": "type", "type": "nominal"},
"y": {"field": "b", "type": "quantitative"},
"color": {
"field": "type",
"type": "nominal",
"scale": {
"domain": ["outside", "inside", "dew"],
"range": ["rgb(0, 0, 0)", "rgb(255, 0, 0)", "rgb(0, 255, 0)"]
}
}
}
}
I don't know of any way to draw this color scheme definition from the data, or to force a legend to be drawn when setting scale to null, but you could hack it by essentially drawing the legend yourself. It might look something like this:
(view in vega editor)
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A bar chart that directly encodes color names in the data.",
"data": {
"values": [
{"color": "rgb(0, 0, 0)", "b": 28, "type": "outside"},
{"color": "rgb(255, 0, 0)", "b": 55, "type": "inside"},
{"color": "rgb(0, 255, 0)", "b": 43, "type": "dew"}
]
},
"hconcat": [
{
"mark": "bar",
"encoding": {
"x": {"field": "type", "type": "nominal"},
"y": {"field": "b", "type": "quantitative"},
"color": {
"field": "color",
"type": "nominal",
"legend": {},
"scale": null
}
}
},
{
"title": "type",
"mark": {"type": "point", "size": 80, "shape": "square", "filled": true},
"encoding": {
"y": {
"field": "type",
"type": "nominal",
"axis": {"orient": "right", "title": null}
},
"color": {"field": "color", "type": "nominal", "scale": null}
}
}
]
}

vega-lite line plot - color not getting applied in transform filter

Vega Editor link here
I've an overlay color change based on filter condition in a multi line chart. Got it working with single line here but 'red' overlay line(along with red dot) doesn't come up with this above multi-line example. Could anyone help me out?
Short answer: your chart is working, except the filtered values are not colored red.
The core issue is that encodings always supersede mark properties, as you can see in this simpler example: editor link
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"description": "A scatterplot showing horsepower and miles per gallons.",
"data": {"url": "data/cars.json"},
"mark": {"type": "point", "color": "red"},
"encoding": {
"x": {"field": "Horsepower", "type": "quantitative"},
"y": {"field": "Miles_per_Gallon", "type": "quantitative"},
"color": {"field": "Origin", "type": "nominal"},
"shape": {"field": "Origin", "type": "nominal"}
}
}
Notice that although we specify that the mark should have color red, this is overridden by the color encoding. This is by design within Vega-Lite, because encodings are more specific than properties.
Back to your chart: because you specify the color encoding in the parent chart, each individual layer inherits that color encoding, and those colors override the "color": "red" that you specify in the individual layers.
To make it do what you want, you can move the color encoding into the individual layers (and use a detail encoding to ensure the data are still grouped by that field). For example (editor link):
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"data": {...},
"width": 1000,
"height": 200,
"autosize": {"type": "pad", "resize": true},
"transform": [
{
"window": [{"op": "rank", "as": "rank"}],
"sort": [{"field": "dateTime", "order": "descending"}]
},
{"filter": "datum.rank <= 100"}
],
"layer": [
{
"mark": {"type": "line"},
"encoding": {
"color": {
"field": "name",
"type": "nominal",
"legend": {"title": "Type"}
}
}
},
{
"mark": {"type": "line", "color": "red"},
"transform": [
{
"as": "count",
"calculate": "if(datum.anomaly == true, datum.count, null)"
},
{"calculate": "true", "as": "baseline"}
]
},
{
"mark": {"type": "circle", "color": "red"},
"transform": [
{"filter": "datum.anomaly == true"},
{"calculate": "true", "as": "baseline"}
]
}
],
"encoding": {
"x": {
"field": "dateTime",
"type": "temporal",
"timeUnit": "hoursminutesseconds",
"sort": {"field": "dateTime", "op": "count", "order": "descending"},
"axis": {"title": "Time", "grid": false}
},
"y": {
"field": "count",
"type": "quantitative",
"axis": {"title": "Count", "grid": false}
},
"detail": {"field": "name", "type": "nominal"}
}
}