I have the following minimal data:
[
{"date": "2019-01-01", "foo": 10000, "bar": 10, "goo": 30},
{"date": "2019-01-02", "foo": 30000, "bar": 20, "goo": 20},
{"date": "2019-01-03", "foo": 40000, "bar": 20, "goo": 10},
{"date": "2019-01-04", "foo": 1000, "bar": 60, "goo": 20}
]
Which I plot using VEGA-LITE:
<!DOCTYPE html>
<html>
<head>
<title>Embedding Vega-Lite</title>
<script src="https://cdn.jsdelivr.net/npm/vega#5.4.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite#3.3.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed#4.2.0"></script>
</head>
<body>
<div id="vis"></div>
<script type="text/javascript">
var yourVlSpec = {
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"Title": "Insights stats",
"description": "Overview of insights stats",
"width": 1000,
"height": 450,
"data": {
"url": "./data.json"
},
"layer": [
{
"mark": "line",
"encoding": {
"x": {
"field": "date",
"type": "temporal",
"title": "Date"
},
"y": {
"field": "foo",
"type": "quantitative",
"title": "Some Foo"
}
}
},
{
"mark": {
"type": "line",
"stroke": "firebrick"
},
"encoding": {
"x": {
"field": "date",
"type": "temporal"
},
"y": {
"field": "bar",
"type": "quantitative",
"title": null,
"scale": { "domain": [0, 100] }
}
}
},
{
"mark": {
"type": "line",
"stroke": "red"
},
"encoding": {
"x": {
"field": "date",
"type": "temporal"
},
"y": {
"field": "goo",
"type": "quantitative",
"title": "Ratio (%)",
"scale": { "domain": [0, 100] }
}
}
}
],
"resolve": { "scale": { "y": "independent" } }
};
vegaEmbed('#vis', yourVlSpec);
</script>
</body>
</html>
I fail to have a proper legend for each line. What am I missing?
Vega-Lite will generate a legend for a chart if there is an encoding that warrants it, such as color, shape, etc.
In the case of plotting multiple columns, a useful pattern is to use the Fold Transform in order to specify your colors via an encoding rather than by manual layering. The result looks something like this (vega editor link):
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"title": "Insights stats",
"description": "Overview of insights stats",
"width": 1000,
"height": 450,
"data": {
"values": [
{"date": "2019-01-01", "foo": 10, "bar": 10, "goo": 30},
{"date": "2019-01-02", "foo": 30, "bar": 20, "goo": 20},
{"date": "2019-01-03", "foo": 40, "bar": 20, "goo": 10},
{"date": "2019-01-04", "foo": 1, "bar": 60, "goo": 20}
]
},
"transform": [
{"fold": ["foo", "bar", "goo"]}
],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "value", "type": "quantitative"},
"color": {"field": "key", "type": "nominal"}
}
}
Related
I am trying to add text label to bar chart, but it not showing it. Here is a example i want to achieve
Here is code
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "background": "#EFF1EF", "width": 500, "height": 26, "autosize":"pad", "data": { "values": [ { "standarts": { "divisions": [ { "a": { "mean": 135, "part1": 10, "part2": 60, "part5": 130,
"part7": 198, "part9": 255, "goal": { "value": 150 } } } ] } } ] }, "transform": [ {"calculate": "datum.standarts.divisions", "as": "D"}, {"flatten": ["D"]}, {"calculate": "datum.D.a", "as": "x"} ], "encoding": { "x": {"field": "x", "type": "quantitative","scale":{"domain":[0,300]},
"stack": null}, "opacity": {"value": 1} }, "layer": [ { "mark":{"type":"bar", "color" : "#b2b7b4", "cornerRadius": 40}, "encoding": {"x": {}} }, { "mark": {"type": "bar", "color": "#0ef9e5", "height": 25}, "encoding": {"x": {"field": "x.mean"}} }, { "mark":{"type":
"text", "align":"center"}, "encoding": {"text": {"field": "x.mean"}} }, { "mark":{"type": "rule"}, "encoding": {"x": {"field":"x.goal.value", "title":["Target"],"axis":{ "titleFont": "Google Sans", "titleFontSize": 16, "titleFontWeight":700, "titleY":
8} }}} ], "config": { "axis": {"ticks": false, "labels": false, "domain": false}, "rule": { "strokeWidth": 4, "strokeDash": [ 0.2, 8 ], "strokeCap": "round", "align":"center" } } }
this is code
And link to editor
vega-lite editor
text part is still not working.
I used documentation on vega-lite website and example codes, but still no success.
Thanks for the help.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"background": "#EFF1EF",
"width": 500,
"height": 26,
"autosize": "pad",
"data": {
"values": [
{
"standarts": {
"divisions": [
{
"a": {
"mean": 135,
"part1": 10,
"part2": 60,
"part5": 130,
"part7": 198,
"part9": 255,
"goal": {"value": 150}
}
}
]
}
}
]
},
"transform": [
{"calculate": "datum.standarts.divisions", "as": "D"},
{"flatten": ["D"]},
{"calculate": "datum.D.a", "as": "x"}
],
"encoding": {
"x": {
"field": "x",
"type": "quantitative",
"scale": {"domain": [0, 300]},
"stack": null
},
"opacity": {"value": 1}
},
"layer": [
{
"mark": {"type": "bar", "color": "#b2b7b4", "cornerRadius": 40},
"encoding": {"x": {}}
},
{
"mark": {"type": "bar", "color": "#0ef9e5", "height": 25},
"encoding": {"x": {"field": "x.mean"}}
},
{
"mark": {"type": "text", "align": "right", "dx": -10},
"encoding": {"text": {"field": "x.mean"}, "x": {"field": "x.mean"}}
},
{
"mark": {"type": "text", "align": "center", "dy": -30},
"encoding": {
"text": {"field": "x.goal.value"},
"x": {"field": "x.goal.value"}
}
},
{
"mark": {"type": "rule"},
"encoding": {
"x": {
"field": "x.goal.value",
"title": ["Target"],
"axis": {
"titleFont": "Google Sans",
"titleFontSize": 16,
"titleFontWeight": 700,
"titleY": 8
}
}
}
}
],
"config": {
"axis": {"ticks": false, "labels": false, "domain": false},
"rule": {
"strokeWidth": 4,
"strokeDash": [0.2, 8],
"strokeCap": "round",
"align": "center"
}
}
}
I am trying to create a VegaLite chart with labelled highlighted areas which are specified in a separate dataset using [min_x, max_x] coordinates.
I've managed to highlight the area itself using a rect mark, but I'm struggling to properly position the label at the top edge of the chart.
This is the end result I'm trying to achieve. In this example I'm using the dy property of the text mark to position the label. Unfortunately this only works when the chart height is known in advance, which doesn't work for my use case.
If there is a better way to achieve the result I want, please let me know. This is the Vegalite specification for the chart above, without previously mentioned dy property:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"datasets": {
"test_data": [
{"x": 0, "y": 1.5},
{"x": 5, "y": 2},
{"x": 9, "y": 4},
{"x": 14, "y": 0}
],
"highlight_data": [
{"from_x": 2.3, "to_x": 3, "label": "AAA"},
{"from_x": 6.3, "to_x": 8, "label": "BBB"}
]
},
"data": {"name": "test_data"},
"layer": [
{
"data": {"name": "highlight_data"},
"transform": [
{"calculate": "(datum.from_x + datum.to_x) / 2", "as": "mean_x"}
],
"layer": [
{
"mark": {"type": "rect", "opacity": 0.3},
"encoding": {
"x": {"field": "from_x", "type": "quantitative"},
"x2": {"field": "to_x"},
"color": {"value": "#fcfc00"}
}
},
{
"mark": {"type": "text"},
"encoding": {
"text": {"field": "label"},
"x": {"field": "mean_x", "type": "quantitative"}
}
}
]
},
{
"mark": {"type": "line"},
"encoding": {
"x": {"field": "x", "type": "quantitative", "title": "X Label"},
"y": {"field": "y", "type": "quantitative", "title": "Y Label"}
}
}
],
"title": "Title",
"width": 800,
"height": 500
}
You can reference height inside an expression to make it dynamic.
"dy": { "expr": "-height + (height/2) -10"}
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"datasets": {
"test_data": [
{"x": 0, "y": 1.5},
{"x": 5, "y": 2},
{"x": 9, "y": 4},
{"x": 14, "y": 0}
],
"highlight_data": [
{"from_x": 2.3, "to_x": 3, "label": "AAA"},
{"from_x": 6.3, "to_x": 8, "label": "BBB"}
]
},
"data": {"name": "test_data"},
"layer": [
{
"data": {"name": "highlight_data"},
"transform": [
{"calculate": "(datum.from_x + datum.to_x) / 2", "as": "mean_x"}
],
"layer": [
{
"mark": {"type": "rect", "opacity": 0.3},
"encoding": {
"x": {"field": "from_x", "type": "quantitative"},
"x2": {"field": "to_x"},
"color": {"value": "#fcfc00"}
}
},
{
"mark": {"type": "text", "dy": { "expr": "-height + (height/2) -10"}},
"encoding": {
"text": {"field": "label"},
"x": {"field": "mean_x", "type": "quantitative"}
}
}
]
},
{
"mark": {"type": "line"},
"encoding": {
"x": {"field": "x", "type": "quantitative", "title": "X Label"},
"y": {"field": "y", "type": "quantitative", "title": "Y Label"}
}
}
],
"title": "Title",
"width": 800,
"height": 500
}
I'm trying to calculate price difference of a selection in a chart provided in Vega Editor.
The goal is to display a price difference in tooltip calculated as end value of selection - start value of selection. I calculate it as price_diff in my code, however the tooltip is displaying NaN, instead of the actual value.
What do I do wrong? Is it possible to set tooltip fields based on selection? I.e. display hover price when not selected and price difference when range is selected?
Thank you for your help
Try this.
Editor
One issue with your original code is that the selection doesn't snap to the nearest point. If you want to solve that too, you can read more about how to do so here.
{
"width": "container",
"data": {
"values": [
{"date": "2021-04-05T00:00", "price": 163.45},
{"date": "2021-04-06T00:00", "price": 161.75},
{"date": "2021-04-07T00:00", "price": 159.42},
{"date": "2021-04-08T00:00", "price": 162.22},
{"date": "2021-04-09T00:00", "price": 161.175},
{"date": "2021-04-12T00:00", "price": 159.77},
{"date": "2021-04-13T00:00", "price": 159.14},
{"date": "2021-04-14T00:00", "price": 158.495},
{"date": "2021-04-15T00:00", "price": 160.775},
{"date": "2021-04-16T00:00", "price": 159.56},
{"date": "2021-04-19T00:00", "price": 156.965},
{"date": "2021-04-20T00:00", "price": 154.525},
{"date": "2021-04-21T00:00", "price": 158.235},
{"date": "2021-04-22T00:00", "price": 155.33},
{"date": "2021-04-23T00:00", "price": 158.985},
{"date": "2021-04-26T00:00", "price": 160.655},
{"date": "2021-04-27T00:00", "price": 159.51},
{"date": "2021-04-28T00:00", "price": 156.11},
{"date": "2021-04-29T00:00", "price": 158.03},
{"date": "2021-04-30T00:00", "price": 153.155},
{"date": "2021-05-03T00:00", "price": 151.3},
{"date": "2021-05-04T00:00", "price": 151.955}
]
},
"encoding": {
"x": {
"field": "date",
"type": "ordinal",
"timeUnit": "yearmonthdatehoursminutes",
"title": "",
"scale": {"paddingInner": 1, "paddingOuter": 0}
},
"y": {
"field": "price",
"type": "quantitative",
"title": "",
"axis": {"formatType": "number"}
}
},
"layer": [
{
"mark": {
"type": "area",
"line": {"color": "red"},
"color": {
"x1": 1,
"y1": 1,
"x2": 1,
"y2": 0,
"gradient": "linear",
"stops": [
{"offset": 0, "color": "white"},
{"offset": 1, "color": "red"}
]
}
}
},
{
"mark": "point",
"encoding": {
"opacity": {
"condition": {"value": 0.8, "param": "hover", "empty": false},
"value": 0
}
}
},
{
"mark": "rule",
"transform": [
{"filter": {"param": "diff"}},
{
"window": [
{"op": "first_value", "field": "price", "as": "first_price"},
{"op": "last_value", "field": "price", "as": "last_price"}
]
},
{
"calculate": "datum.last_price - datum.first_price",
"as": "price_diff"
}
],
"encoding": {
"opacity": {
"condition": {"value": 0.2, "param": "hover", "empty": false},
"value": 0
},
"tooltip": [
{
"field": "date",
"type": "nominal",
"formatType": "time",
"title": "Date"
},
{
"field": "price",
"type": "quantitative",
"format": "$.2f",
"title": "Price"
},
{
"field": "price_diff",
"type": "quantitative",
"title": "Price difference"
}
]
},
"params": [
{
"name": "hover",
"select": {
"type": "point",
"fields": ["price"],
"nearest": true,
"on": "mouseover",
"clear": "mouseout",
"encodings": ["x"]
}
},
{
"name": "diff",
"select": {"type": "interval", "encodings": ["x"]}
}
]
}
]
}
I am working with Elasticsearch which provides the min, max, Q1, Q2 and Q3 data. All I have to do is to plot it in form of a box plot. Kibana as of now only supports vega-lite version 2.6.0 and vega 4.3.0.
Here is a complete sample I have made.
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.json",
"width": 100,
"height": 200,
"padding": 10,
"data": {
"name": "sample",
"values": [
{
"task": "A",
"min" : 72.66500091552734,
"max" : 139.54299926757812,
"q1" : 98.68599700927734,
"q2" : 120.12850189208984,
"q3" : 121.82099914550781
},
{
"task": "B",
"min" : 71.66500091552734,
"max" : 159.54299926757812,
"q1" : 88.68599700927734,
"q2" : 110.12850189208984,
"q3" : 141.82099914550781
},
{
"task": "c",
"min" : 45.66500091552734,
"max" : 169.54299926757812,
"q1" : 88.68599700927734,
"q2" : 110.12850189208984,
"q3" : 141.82099914550781
}
]
},
"layer": [
{
"width": 5,
"encoding": {
"x": {"type": "ordinal","field": "task"},
"y": {"type": "quantitative","field": "min"},
"y2": {"type": "quantitative","field": "max"},
"color": {"value": "#2CB5E8"}
},
"mark": {
"type": "bar"
}
},
{
"width": 20,
"encoding": {
"x": {"type": "ordinal","field": "task"},
"y": {"type": "quantitative","field": "q1"},
"y2": {"type": "quantitative","field": "q3"},
"color": {"value": "#EB985E"}
},
"mark": "bar"
},
{
"encoding": {
"x": {"type": "ordinal","field": "task"},
"y": {"type": "quantitative","field": "q2"},
"color": {"value": "#090502"}
},
"mark": "point"
}
]
}
This is what the plot looks like:
But box plot look something like this
The current version of vega-lite does support the boxplot. But I am stuck with older version.
I am trying to reduce the width of the bar plot for min and max. And keep it thick for Q1 and Q3. Somehow it is not working.
Also is it possible to plot Q2 as a flat line instead of a point?
You can construct a boxplot manually using a layer chart with a bar, tick, and rule mark. For example (view in editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.json",
"width": 100,
"height": 200,
"data": {
"name": "sample",
"values": [
{
"task": "A",
"min": 72.66500091552734,
"max": 139.54299926757812,
"q1": 98.68599700927734,
"q2": 120.12850189208984,
"q3": 121.82099914550781
},
{
"task": "B",
"min": 71.66500091552734,
"max": 159.54299926757812,
"q1": 88.68599700927734,
"q2": 110.12850189208984,
"q3": 141.8209991455078
},
{
"task": "c",
"min": 45.66500091552734,
"max": 169.54299926757812,
"q1": 88.68599700927734,
"q2": 110.12850189208984,
"q3": 141.8209991455078
}
]
},
"layer": [
{
"encoding": {
"x": {"type": "ordinal", "field": "task"},
"y": {"type": "quantitative", "field": "min"},
"y2": {"type": "quantitative", "field": "max"}
},
"mark": {"type": "rule", "color": "black"}
},
{
"encoding": {
"x": {"type": "ordinal", "field": "task"},
"y": {"type": "quantitative", "field": "q1"},
"y2": {"type": "quantitative", "field": "q3"}
},
"mark": {"type": "bar", "color": "#EB985E", "size": 20}
},
{
"encoding": {
"x": {"type": "ordinal", "field": "task"},
"y": {"type": "quantitative", "field": "q2"}
},
"mark": {"type": "tick", "color": "gray", "size": 20}
}
]
}
(This is a follow up on this question)
Assume my data looks like:
[
{"date": "2019-01-01", "foo": 10000, "bar": 10, "goo": 30},
{"date": "2019-01-02", "foo": 30000, "bar": 20, "goo": 20},
{"date": "2019-01-03", "foo": 40000, "bar": 20, "goo": 10},
{"date": "2019-01-04", "foo": 20000, "bar": 60, "goo": 20}
]
And my plot is:
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"description": "Stock prices of 5 Tech Companies over Time.",
"width": 1200,
"height": 450,
"data": { "url": "data.json" },
"mark": {
"type": "line",
"point": true
},
"transform": [
{ "fold": ["foo", "bar", "goo"] }
],
"encoding": {
"x": { "field": "date", "type": "temporal" },
"y": { "field": "value", "type": "quantitative" },
"color": { "field": "key", "type": "nominal" },
"scale": {"zero": false}
},
"resolve": { "scale": { "y": "independent" } }
}
As you can see, due to the different order of magnitude of foo and the other two columns, the plot is not helpful. How can I have a secondary y-axis and (mention it in the legend)?
You can do that by combining layering with the fold transform. Here is how you might modify your example (vega editor link):
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"width": 1200,
"height": 450,
"data": {
"values": [
{"date": "2019-01-01", "foo": 10000, "bar": 10, "goo": 30},
{"date": "2019-01-02", "foo": 30000, "bar": 20, "goo": 20},
{"date": "2019-01-03", "foo": 40000, "bar": 20, "goo": 10},
{"date": "2019-01-04", "foo": 20000, "bar": 60, "goo": 20}
]
},
"transform": [{"fold": ["foo", "bar", "goo"]}],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "value", "type": "quantitative"},
"color": {"field": "key", "type": "nominal"}
},
"layer": [
{
"mark": {"type": "line", "point": true},
"transform": [{"filter": "datum.key == 'foo'"}]
},
{
"mark": {"type": "line", "point": true},
"transform": [{"filter": "datum.key != 'foo'"}]
}
],
"resolve": {"scale": {"y": "independent"}}
}
You could then go on to modify the axis titles by specifying the y encoding & title within each layer. Here is an example (vega editor link):
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"width": 1200,
"height": 450,
"data": {
"values": [
{"date": "2019-01-01", "foo": 10000, "bar": 10, "goo": 30},
{"date": "2019-01-02", "foo": 30000, "bar": 20, "goo": 20},
{"date": "2019-01-03", "foo": 40000, "bar": 20, "goo": 10},
{"date": "2019-01-04", "foo": 20000, "bar": 60, "goo": 20}
]
},
"transform": [{"fold": ["foo", "bar", "goo"]}],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"color": {"field": "key", "type": "nominal"}
},
"layer": [
{
"mark": {"type": "line", "point": true},
"encoding": {
"y": {"field": "value", "type": "quantitative", "title": "Foo Value"}
},
"transform": [{"filter": "datum.key == 'foo'"}]
},
{
"mark": {"type": "line", "point": true},
"encoding": {
"y": {
"field": "value",
"type": "quantitative",
"title": "Bar/Goo Value"
}
},
"transform": [{"filter": "datum.key != 'foo'"}]
}
],
"resolve": {"scale": {"y": "independent"}}
}