Deneb, how to create line chart with horizontal and vertical lines and labels - vega-lite

What would a Deneb (Vega Lite) specification look like to draw a line chart like this + horizontal and vertical line with a custom label where those horizontal and vertical lines meet the axis?
Okay, so this was my attempt. I need help - do not know how to add labels where the horizontal and vertical lines meet the y and x axis?
{
"data": {
"values": [
{"date": "2010-01-01", "price": "300", "source": "A"},
{"date": "2011-01-01", "price": "315", "source": "A"},
{"date": "2012-01-01", "price": "285", "source": "A"},
{"date": "2013-01-01", "price": "345", "source": "A"},
{"date": "2014-01-01", "price": "365", "source": "A"},
{"date": "2015-01-01", "price": "385", "source": "A"},
{"date": "2016-01-01", "price": "415", "source": "A"},
{"date": "2017-01-01", "price": "400", "source": "A"},
{"date": "2018-01-01", "price": "380", "source": "A"},
{"date": "2019-01-01", "price": "270", "source": "A"},
{"date": "2020-01-01", "price": "325", "source": "A"},
{"date": "2021-01-01", "price": "345", "source": "A"},
{"date": "2022-01-01", "price": "360", "source": "A"},
{"date": "2015-01-01", "price": "385", "source": "B"},
{"date": "2010-01-01", "price": "385", "source": "B"},
{"date": "2015-01-01", "price": "385", "source": "C"},
{"date": "2015-01-01", "price": "0", "source": "C"}
]
},
"layer" : [
{
"width": 500,
"height": 250,
"mark": "line",
"transform": [{"filter": "datum.source==='A'"}],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
},
{
"mark": {"type":"line", "strokeDash": [3,1]},
"transform": [{"filter": "datum.source==='B'"}],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
},
{
"mark": {"type":"line", "strokeDash": [3,1]},
"transform": [{"filter": "datum.source==='C'"}],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
}
]
}

Try this.
{
"data": {
"values": [
{"date": "2010-01-01", "price": "300", "source": "A"},
{"date": "2011-01-01", "price": "315", "source": "A"},
{"date": "2012-01-01", "price": "285", "source": "A"},
{"date": "2013-01-01", "price": "345", "source": "A"},
{"date": "2014-01-01", "price": "365", "source": "A"},
{"date": "2015-01-01", "price": "385", "source": "A"},
{"date": "2016-01-01", "price": "415", "source": "A"},
{"date": "2017-01-01", "price": "400", "source": "A"},
{"date": "2018-01-01", "price": "380", "source": "A"},
{"date": "2019-01-01", "price": "270", "source": "A"},
{"date": "2020-01-01", "price": "325", "source": "A"},
{"date": "2021-01-01", "price": "345", "source": "A"},
{"date": "2022-01-01", "price": "360", "source": "A"},
{"date": "2015-01-01", "price": "385", "source": "B"},
{"date": "2010-01-01", "price": "385", "source": "B"},
{"date": "2015-01-01", "price": "385", "source": "C"},
{"date": "2015-01-01", "price": "0", "source": "C"}
]
},
"width": 500,
"height": 250,
"layer": [
{
"mark": "line",
"transform": [{"filter": "datum.source==='A'"}],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
},
{
"mark": {"type": "line", "strokeDash": [3, 1]},
"transform": [{"filter": "datum.source==='B'"}],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
},
{
"mark": {"type": "line", "strokeDash": [3, 1]},
"transform": [{"filter": "datum.source==='C'"}],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
},
{
"data": {"values": [{}]},
"mark": {
"type": "text",
"text": "Label A",
"dx": -50,
"dy": 0,
"color": "red"
},
"encoding": {"x": {"datum": {"year": 2010}}, "y": {"datum": 385}}
},
{
"data": {"values": [{}]},
"mark": {
"type": "text",
"text": "Label B",
"dx": 0,
"dy": 30,
"color": "red"
},
"encoding": {"x": {"datum": {"year": 2015}}, "y": {"datum": 0}}
}
]
}

Related

How to show selection / calculated data in vega-lite tooltip?

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"]}
}
]
}
]
}

How do I make the outer and inner donut charts a full circle if their value are not the same?

I want to have two donut charts in one visual where the outer and inner represent a different year and both are a full circle. The outer or inner donut does not make a full circle if the outer and inner donut does not add up to the same number. I tried to use some transforms outside the layer, but that did not work. I think the problem is outside the layer properties, but I am not sure where to get started.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"date": "3/2/2020", "brand": "Hair", "mentions": 1463},
{"date": "8/19/2020", "brand": "Fragrance", "mentions": 1912},
{"date": "10/14/2020", "brand": "Fragrance", "mentions": 6804},
{"date": "5/7/2020", "brand": "Makeup", "mentions": 4264},
{"date": "5/7/2021", "brand": "Makeup", "mentions": 4264},
{"date": "8/4/2021", "brand": "Fragrance", "mentions": 9007}
]
},
"encoding": {
"theta": {
"field": "mentions",
"type": "quantitative",
"stack": true,
"aggregate": "sum"
}
},
"layer": [
{
"mark": {"type": "arc", "radius2": 100, "radius": 140},
"transform": [{"filter": {"field": "date", "timeUnit": "year", "equal": 2020}}],
"encoding": {
"color": {
"field": "brand",
"type": "nominal",
"scale": {"range": "category"}
}
}
},
{
"mark": {"type": "text", "radius": 120, "color": "white"},
"transform": [{"filter": {"field": "date", "timeUnit": "year", "equal": 2020}}],
"encoding": {
"text": {
"field": "mentions",
"type": "quantitative",
"aggregate": "sum"
},
"detail": {"field": "brand", "type": "nominal"}
}
},
{
"mark": {"type": "arc", "radius2": 150, "radius": 190},
"transform": [{"filter": {"field": "date", "timeUnit": "year", "equal": 2021}}],
"encoding": {
"color": {
"field": "brand",
"type": "nominal",
"scale": {"range": "category"}
}
}
},
{
"mark": {"type": "text", "radius": 170, "color": "white"},
"transform": [{"filter": {"field": "date", "timeUnit": "year", "equal": 2021}}],
"encoding": {
"text": {
"field": "mentions",
"type": "quantitative",
"aggregate": "sum"
},
"detail": {"field": "brand", "type": "nominal"}
}
}
],
"view": {"stroke": null}
}
Adding the config resolve for theta seems to resolve your issue. It is probably using shared encoding so that might causing the calculation error.
Below is the modified code and editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"date": "3/2/2020", "brand": "Hair", "mentions": 1463},
{"date": "8/19/2020", "brand": "Fragrance", "mentions": 1912},
{"date": "10/14/2020", "brand": "Fragrance", "mentions": 6804},
{"date": "5/7/2020", "brand": "Makeup", "mentions": 4264},
{"date": "5/7/2021", "brand": "Makeup", "mentions": 4264},
{"date": "8/4/2021", "brand": "Fragrance", "mentions": 9007}
]
},
"encoding": {
"theta": {
"field": "mentions",
"type": "quantitative",
"stack": true,
"aggregate": "sum"
}
},
"layer": [
{
"mark": {"type": "arc", "radius2": 100, "radius": 140},
"transform": [
{"filter": {"field": "date", "timeUnit": "year", "equal": 2020}}
],
"encoding": {
"color": {
"field": "brand",
"type": "nominal",
"scale": {"range": "category"}
}
}
},
{
"mark": {"type": "text", "radius": 120, "color": "white"},
"transform": [
{"filter": {"field": "date", "timeUnit": "year", "equal": 2020}}
],
"encoding": {
"text": {
"field": "mentions",
"type": "quantitative",
"aggregate": "sum"
},
"detail": {"field": "brand", "type": "nominal"}
}
},
{
"mark": {"type": "arc", "radius2": 150, "radius": 190},
"transform": [
{"filter": {"field": "date", "timeUnit": "year", "equal": 2021}}
],
"encoding": {
"color": {
"field": "brand",
"type": "nominal",
"scale": {"range": "category"}
}
}
},
{
"mark": {"type": "text", "radius": 170, "color": "white"},
"transform": [
{"filter": {"field": "date", "timeUnit": "year", "equal": 2021}}
],
"encoding": {
"text": {
"field": "mentions",
"type": "quantitative",
"aggregate": "sum"
},
"detail": {"field": "brand", "type": "nominal"}
}
}
],
"resolve": {"scale": {"theta": "independent"}},
"view": {"stroke": null}
}

How to display the aggregated sum value inside a pie chart with different color?

I could get the value of each brand inside the pie chart by adjusting the radius, but I could not change the color without causing the whole pie chart to be black. I believe that I might need to transform for the sum of each brand, but getting the correct value in the correct position seems to be my main issue.
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A simple pie chart with labels.",
"height": 500,
"width": 500,
"data": {
"values": [
{"date": "4/15/2020", "brand": "Body Care", "mentions": 8599},
{"date": "4/7/2020", "brand": "Makeup", "mentions": 9090},
{"date": "6/29/2020", "brand": "Body Care", "mentions": 4563},
{"date": "11/7/2020", "brand": "Skincare", "mentions": 3369},
{"date": "10/10/2020", "brand": "Fragrance", "mentions": 7025},
{"date": "10/25/2020", "brand": "Skincare", "mentions": 3523},
{"date": "2/21/2020", "brand": "Fragrance", "mentions": 7976},
{"date": "3/2/2020", "brand": "Hair", "mentions": 1463},
{"date": "8/19/2020", "brand": "Fragrance", "mentions": 1912},
{"date": "10/14/2020", "brand": "Fragrance", "mentions": 6804},
{"date": "5/7/2020", "brand": "Makeup", "mentions": 4264},
{"date": "8/4/2020", "brand": "Fragrance", "mentions": 9007},
{"date": "9/17/2020", "brand": "Fragrance", "mentions": 5876},
{"date": "1/12/2020", "brand": "Fragrance", "mentions": 5675},
{"date": "7/17/2020", "brand": "Skincare", "mentions": 2555},
{"date": "1/29/2020", "brand": "Body Care", "mentions": 6824},
{"date": "9/19/2020", "brand": "Hair", "mentions": 3109},
{"date": "2/4/2020", "brand": "Body Care", "mentions": 5807},
{"date": "4/15/2020", "brand": "Fragrance", "mentions": 4999}
]
},
"encoding": {
"theta": {
"field": "mentions",
"type": "quantitative",
"stack": true,
"aggregate": "sum"
},
"color": {
"field": "brand",
"type": "nominal",
"legend": null,
"scale": {"range": "category"}
}
},
"layer": [
{"mark": {"type": "arc", "outerRadius": 200}},
{
"mark": {"type": "text", "radius": 250, "fontSize": 16},
"encoding": {"text": {"field": "brand", "type": "nominal"}, "color": {}}
},
{
"mark": {"type": "text", "radius": 300, "color": "blue"},
"encoding": {
"text": {
"field": "mentions",
"type": "quantitative",
"aggregate": "sum"
},
"color": {"field": "brand", "type": "nominal"}
}
}
],
"view": {"stroke": null}
}
You can move the "color" encoding into the layer where you want it to apply, and then use a "detail" encoding to group the text without adding a color scale (view in editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A simple pie chart with labels.",
"height": 500,
"width": 500,
"data": {
"values": [
{"date": "4/15/2020", "brand": "Body Care", "mentions": 8599},
{"date": "4/7/2020", "brand": "Makeup", "mentions": 9090},
{"date": "6/29/2020", "brand": "Body Care", "mentions": 4563},
{"date": "11/7/2020", "brand": "Skincare", "mentions": 3369},
{"date": "10/10/2020", "brand": "Fragrance", "mentions": 7025},
{"date": "10/25/2020", "brand": "Skincare", "mentions": 3523},
{"date": "2/21/2020", "brand": "Fragrance", "mentions": 7976},
{"date": "3/2/2020", "brand": "Hair", "mentions": 1463},
{"date": "8/19/2020", "brand": "Fragrance", "mentions": 1912},
{"date": "10/14/2020", "brand": "Fragrance", "mentions": 6804},
{"date": "5/7/2020", "brand": "Makeup", "mentions": 4264},
{"date": "8/4/2020", "brand": "Fragrance", "mentions": 9007},
{"date": "9/17/2020", "brand": "Fragrance", "mentions": 5876},
{"date": "1/12/2020", "brand": "Fragrance", "mentions": 5675},
{"date": "7/17/2020", "brand": "Skincare", "mentions": 2555},
{"date": "1/29/2020", "brand": "Body Care", "mentions": 6824},
{"date": "9/19/2020", "brand": "Hair", "mentions": 3109},
{"date": "2/4/2020", "brand": "Body Care", "mentions": 5807},
{"date": "4/15/2020", "brand": "Fragrance", "mentions": 4999}
]
},
"encoding": {
"theta": {
"field": "mentions",
"type": "quantitative",
"stack": true,
"aggregate": "sum"
}
},
"layer": [
{
"mark": {"type": "arc", "outerRadius": 200},
"encoding": {
"color": {
"field": "brand",
"type": "nominal",
"legend": null,
"scale": {"range": "category"}
}
}
},
{
"mark": {"type": "text", "radius": 250, "fontSize": 16},
"encoding": {"text": {"field": "brand", "type": "nominal"}}
},
{
"mark": {"type": "text", "radius": 300, "color": "blue"},
"encoding": {
"text": {
"field": "mentions",
"type": "quantitative",
"aggregate": "sum"
},
"detail": {"field": "brand", "type": "nominal"}
}
}
],
"view": {"stroke": null}
}

Plot two "columns" of data having two different orders of magnitude using vega-lite

(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"}}
}

how to define json for multi-line graph data

I have been trying to find out how to define the data for a multi-line graph in vega-lite but I can't get it to work. The examples show data for a csv file at a URL endpoint ( https://vega.github.io/vega-editor/?mode=vega-lite&spec=line_color&showEditor=1 ), but I want to view the data I define in a simple json.
Here is what I have for a single line graph:
var LineSpec = {
"description": "variation over time for",
"data": {
"values":
[
{"date": "2012-04-23T18:25:43.511Z","price": 10},
{"date": "2012-04-25T18:25:43.511Z","price": 7},
{"date": "2012-04-27T18:25:43.511Z","price": 4},
{"date": "2012-05-01T18:25:43.511Z","price": 1},
{"date": "2012-05-03T18:25:43.511Z","price": 2},
{"date": "2012-05-05T18:25:43.511Z","price": 6},
{"date": "2012-05-07T18:25:43.511Z","price": 8},
{"date": "2012-05-09T18:25:43.511Z","price": 4},
{"date": "2012-05-11T18:25:43.511Z","price": 7}
]
},
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"},
"color": {"field": "symbol", "type": "nominal"}
}
};
How do I modify "data" so as display a multiline graph? (and if possible display more useful information that undefined in the symbol table). Here is what I see right now:
Line graph with undefined symbol
Thank you!
You will have to add the symbol field to your data. I added the symbol field and symbols A and B. This data should render a multi-line graph with the two symbols in the legend:
{
"description": "variation over time for",
"data": {
"values": [
{"date": "2012-04-23T18:25:43.511Z","price": 10, "symbol": "A"},
{"date": "2012-04-25T18:25:43.511Z","price": 7, "symbol": "B"},
{"date": "2012-04-27T18:25:43.511Z","price": 4, "symbol": "A"},
{"date": "2012-05-01T18:25:43.511Z","price": 1, "symbol": "B"},
{"date": "2012-05-03T18:25:43.511Z","price": 2, "symbol": "A"},
{"date": "2012-05-05T18:25:43.511Z","price": 6, "symbol": "B"},
{"date": "2012-05-07T18:25:43.511Z","price": 8, "symbol": "A"},
{"date": "2012-05-09T18:25:43.511Z","price": 4, "symbol": "B"},
{"date": "2012-05-11T18:25:43.511Z","price": 7, "symbol": "A"}
]
},
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"},
"color": {"field": "symbol", "type": "nominal"}
}
}