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

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

Related

my picked_store on Vega-lite is not functioning. I'm wanting to select filter datapoints by year

This element of my Vega-lite does not pick up on the desired data. Im wanting the selector to filter data, depending upon the net-zero year
Are my options in the wrong format? Is having a mix of integers and "No Target Selected" invalidating my picked_store?
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Equal earth map depicting CO2 emissions per capita. Some countries did not produce any estimates.",
"title": {
"text": "Greenhouse Gas Emissions Against CCS Readiness",
"subtitle": "CO₂ emissions (metric tonne per capita). Source: Our World in Data",
"subtitleFontStyle": "italic",
"subtitleFontSize": 10,
"anchor": "start",
"color": "rgba(58, 59, 60)"
},
"height": 500,
"width": 545,
"background": null,
"data": {
"url": "https://raw.githubusercontent.com/jameseconnolly/jameseconnolly.github.io/main/Carbon_Capture_Requirement.csv",
"format": {"type": "csv"}
},
"layer": [
{
"selection": {
"picked": {
"empty": "none",
"bind": {
"Net-zero Target": {
"input": "select",
"options": [
"No Target Selected",
0,
2000,
2030,
2035,
2040,
2045,
2050,
2053,
2060,
2065,
2070
],
"name": "Net-zero Target:"
}
},
"type": "single",
"fields": ["Net-zero Target"]
},
"grid": {
"type": "interval",
"bind": "scales",
"on": "[mousedown, window:mouseup] > window:mousemove!",
"translate": "[mousedown, window:mouseup] > window:mousemove!",
"zoom": "wheel!",
"resolve": "global"
}
},
"mark": {"type": "point", "filled": true},
"encoding": {
"color": {
"value": "grey",
"condition": {
"field": "Cluster",
"selection": "picked",
"type": "nominal",
"legend": null
}
},
"size": {
"value": 60,
"condition": {"value": 120, "selection": "picked"}
},
"opacity": {
"value": 0.4,
"condition": {"value": 1, "selection": "picked"}
},
"x": {
"field": "Carbon Capture Requirement",
"scale": {"zero": false},
"type": "quantitative",
"title": null,
"axis": {
"grid": false,
"title": "Carbon Capture and Storage Readiness"
}
},
"y": {
"field": "log_GHG",
"scale": {"zero": false},
"type": "quantitative",
"axis": {
"grid": false,
"title": "Log Greenhouse Gas Emissions (MT CO2e)"
}
}
}
},
{
"data": {"values": [{"y": "17", "x": "0"}, {"y": "23", "x": "90"}]},
"mark": {"type": "line", "strokeDash": [9, 1], "color": "#ff0101"},
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
}
},
{
"mark": {"type": "text", "x": 540, "align": "right", "y": 20, "size": 25},
"transform": [{"calculate": "0.1", "as": "R2"}],
"encoding": {"text": {"type": "nominal", "field": "R2"}}
}
]
}
Is the following what you want?
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Equal earth map depicting CO2 emissions per capita. Some countries did not produce any estimates.",
"title": {
"text": "Greenhouse Gas Emissions Against CCS Readiness",
"subtitle": "CO₂ emissions (metric tonne per capita). Source: Our World in Data",
"subtitleFontStyle": "italic",
"subtitleFontSize": 10,
"anchor": "start",
"color": "rgba(58, 59, 60)"
},
"height": 500,
"width": 545,
"data": {
"url": "https://raw.githubusercontent.com/jameseconnolly/jameseconnolly.github.io/main/Carbon_Capture_Requirement.csv",
"format": {"type": "csv"}
},
"layer": [
{
"params": [
{
"name": "year",
"select": {"type": "point", "fields": ["Net-zero Target"]},
"bind": {
"input": "select",
"options": [
"",
"2000.0",
"2030.0",
"2050.0"
]
}
}
],
"mark": {"type": "point", "filled": true},
"encoding": {
"color": {
"condition": {
"param": "year",
"field": "Net-zero Target",
"type": "nominal"
},
"value": "grey"
},
"size": {"value": 60},
"opacity": {"value": 0.4},
"x": {
"field": "Carbon Capture Requirement",
"scale": {"zero": false},
"type": "quantitative",
"title": null,
"axis": {
"grid": false,
"title": "Carbon Capture and Storage Readiness"
}
},
"y": {
"field": "log_GHG",
"scale": {"zero": false},
"type": "quantitative",
"axis": {
"grid": false,
"title": "Log Greenhouse Gas Emissions (MT CO2e)"
}
}
}
},
{
"data": {"values": [{"y": "17", "x": "0"}, {"y": "23", "x": "90"}]},
"mark": {"type": "line", "strokeDash": [9, 1], "color": "#ff0101"},
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
}
},
{
"mark": {"type": "text", "x": 540, "align": "right", "y": 20, "size": 25},
"transform": [{"calculate": "0.1", "as": "R2"}],
"encoding": {"text": {"type": "nominal", "field": "R2"}}
}
]
}

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

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

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

Is it possible to have columns of donut chart with gray arc indicating the missing part?

Currently, the donut chart assumed that the max value is 100%. What I would like is for the category Chinese to have a percentage of 50% with gray arc indicating the missing 50%. The two other donut charts will behave similarly in their respective column.
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A simple donut chart with embedded data.",
"data": {
"values": [
{"category": "English", "value": 4},
{"category": "Malay", "value": 6},
{"category": "Chinese", "value": 10}
]
},
"mark": {"type": "arc", "innerRadius": 80},
"encoding": {
"column": {"field": "category"},
"theta": {"field": "value", "type": "quantitative"},
"color": {"field": "category", "type": "nominal"}
},
"view": {"stroke": null}
}
It's a bit more complex, but one way to do this is to use a transform to calculate the total, and then a layer chart to plot that total in the background.
Here is an example (open in editor):
{
"data": {
"values": [
{"category": "English", "value": 4},
{"category": "Malay", "value": 6},
{"category": "Chinese", "value": 10}
]
},
"transform": [
{"joinaggregate": [{"op": "sum", "field": "value", "as": "total"}]}
],
"facet": {"column": {"field": "category"}},
"spec": {
"layer": [
{
"mark": {"type": "arc", "innerRadius": 80, "color": "lightgray"},
"encoding": {"theta": {"field": "total", "type": "quantitative"}}
},
{
"mark": {"type": "arc", "innerRadius": 80},
"encoding": {
"theta": {"field": "value", "type": "quantitative"},
"color": {"field": "category"}
}
}
],
"view": {"stroke": null}
}
}

Pulling values from a csv file in JSON [SyntaxError: Unexpected token a in JSON at position 0]

I'm using VEGA with the code at the bottom of this post. The code works fine when I manually specify values for a, b, c and d.
Now I'm trying to change the code so that rather than manually specifying the values for a-d, it reads it from a csv file [which looks like this:
[
However my problem is that the graph fails to display any info, instead I get the following error in chrome's console:
This is my configuration file:
{
"$schema": "https://vega.github.io/schema/vega/v4.json",
"width": 400,
"padding": 5,
"autosize": "pad",
"data": [
{
"url": "data/summary3.csv",
"name": "tuples",
"transform": [
{
"type": "aggregate",
"groupby": ["a", "b", "d"],
"fields": ["c"],
"ops": ["average"],
"as": ["c"]
}
]
},
{
"name": "trellis",
"source": "tuples",
"transform": [
{"type": "aggregate", "groupby": ["a"]},
{
"type": "formula",
"as": "span",
"expr": "rangeStep * bandspace(datum.count, innerPadding, outerPadding)"
},
{"type": "stack", "field": "span"},
{"type": "extent", "field": "y1", "signal": "trellisExtent"}
]
}
],
"legends": [
{"fill": "color", "orient": "right", "title": "Objective Categories"}
],
"signals": [
{"name": "rangeStep", "value": 20},
{"name": "innerPadding", "value": 0.1},
{"name": "outerPadding", "value": 0.2},
{"name": "height", "update": "trellisExtent[1]"},
{"name": "colors", "value": ["#1f77b4", "#2ca02c", "#ff7f0e", "#1f77b4"]}
],
"scales": [
{
"name": "xscale",
"domain": {"data": "tuples", "field": "c"},
"nice": true,
"zero": true,
"round": true,
"range": "width"
},
{
"name": "color",
"type": "ordinal",
"range": {"signal": "colors"},
"domain": {"data": "trellis", "field": "a"}
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"title": "Percent complete",
"ticks": true,
"labels": true,
"grid": true,
"domain": true
}
],
"marks": [
{
"type": "group",
"from": {
"data": "trellis",
"facet": {"name": "faceted_tuples", "data": "tuples", "groupby": "a"}
},
"encode": {
"enter": {"x": {"value": 0}, "width": {"signal": "width"}},
"update": {"y": {"field": "y0"}, "y2": {"field": "y1"}}
},
"scales": [
{
"name": "yscale",
"type": "band",
"paddingInner": {"signal": "innerPadding"},
"paddingOuter": {"signal": "outerPadding"},
"round": true,
"domain": {"data": "faceted_tuples", "field": "b"},
"range": {"step": {"signal": "rangeStep"}}
}
],
"axes": [
{
"orient": "left",
"scale": "yscale",
"ticks": false,
"domain": false,
"labelPadding": 4
}
],
"marks": [
{
"type": "rect",
"from": {"data": "faceted_tuples"},
"encode": {
"enter": {
"x": {"value": 0},
"x2": {"scale": "xscale", "field": "c"},
"fill": {"scale": "color", "field": "a"},
"strokeWidth": {"value": 2},
"tooltip": {"field": "d"},
"hover": {"fill": {"value": "red"}}
},
"update": {
"y": {"scale": "yscale", "field": "b"},
"height": {"scale": "yscale", "band": 1},
"stroke": {"value": null},
"zindex": {"value": 0}
},
"hover": {"stroke": {"value": "firebrick"}, "zindex": {"value": 1}}
}
}
]
}
]
}
Your example works if you add "format": {"type":"csv"} into the spec after line 9, i.e.
...
"name": "tuples",
"format": {"type":"csv"},
"transform": [
{
...
The error message is saying it's trying to parse the csv file as json. I'm not sure why it doesn't auto detect from the file extension like it does in vega lite, but it looks from the docs like this is expected behaviour:
https://vega.github.io/vega/docs/data/#format