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