Calculate time from given date and hour - vega-lite

It seems to be a simple question, but there is surprisingly lack of documentation covering that basic transformation.
With a given data:
{"date": "2022-12-28", "hr": 10, "temp": 5.7},
{"date": "2022-12-28", "hr": 9, "temp": 5.0},
...and so on...
There is need to create datetime value.
Lets say We will try this transformation:
{"calculate": "time(datum.date + 'T' + datum.hr + ':00:00')", "as": "t"}
It works perfectly, but only for two-digit input (hr 10-23). Which gives as output:
data_0:
date hr temp t
"2022-12-28" 10 5.7 1672218000000
"2022-12-27" 23 2.2 1672178400000
"2022-12-27" 22 2.5 1672174800000
And clearly ignoring one digit integers.
Opposite, transformation:
{"calculate": "time(datum.date + 'T0' + datum.hr + ':00:00')", "as": "t"}
Will catch only one-digit integers, ignorig all the rest.
The question is: What vanilla Vega-Lite function should be used in this case.
Below is working Vega-Lite configuration:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Temp. hour by hour.",
"width": "container",
"data": {"values": [
{"date": "2022-12-28", "hr": 10, "temp": 5.7},
{"date": "2022-12-28", "hr": 9, "temp": 5.0},
{"date": "2022-12-28", "hr": 8, "temp": 3.8},
{"date": "2022-12-28", "hr": 7, "temp": 3.1},
{"date": "2022-12-28", "hr": 6, "temp": 2.7},
{"date": "2022-12-28", "hr": 5, "temp": 2.1},
{"date": "2022-12-28", "hr": 4, "temp": 1.9},
{"date": "2022-12-28", "hr": 3, "temp": -1.2},
{"date": "2022-12-28", "hr": 2, "temp": 1.0},
{"date": "2022-12-28", "hr": 1, "temp": 1.2},
{"date": "2022-12-28", "hr": 0, "temp": 1.5},
{"date": "2022-12-27", "hr": 23, "temp": 2.2},
{"date": "2022-12-27", "hr": 22, "temp": 2.5}
]},
"transform": [
{"calculate": "time(datum.date + 'T' + datum.hr + ':00:00')", "as": "t"}
],
"encoding": {
"x": {"field": "t", "type": "temporal", "title": "Time"},
"y": {"type": "quantitative", "axis": {"title": "Temp.[°C]"}}
},
"layer": [
{"mark": {"type": "circle", "opacity": 0.75, "tooltip": true},
"encoding": {
"y": {"field": "temp", "title": "Temp."},
"color": {"field": "temp", "type": "quantitative",
"scale": {"domainMid": 0, "scheme": "viridis"}, "title": "[°C]"}
}
}
]
}

You're best doing stuff like this upstream but you can still do it in Vega. e.g.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Temp. hour by hour.",
"width": "container",
"data": {
"values": [
{"date": "2022-12-28", "hr": 10, "temp": 5.7},
{"date": "2022-12-28", "hr": 9, "temp": 5},
{"date": "2022-12-28", "hr": 8, "temp": 3.8},
{"date": "2022-12-28", "hr": 7, "temp": 3.1},
{"date": "2022-12-28", "hr": 6, "temp": 2.7},
{"date": "2022-12-28", "hr": 5, "temp": 2.1},
{"date": "2022-12-28", "hr": 4, "temp": 1.9},
{"date": "2022-12-28", "hr": 3, "temp": -1.2},
{"date": "2022-12-28", "hr": 2, "temp": 1},
{"date": "2022-12-28", "hr": 1, "temp": 1.2},
{"date": "2022-12-28", "hr": 0, "temp": 1.5},
{"date": "2022-12-27", "hr": 23, "temp": 2.2},
{"date": "2022-12-27", "hr": 22, "temp": 2.5}
]
},
"transform": [
{
"calculate": " datetime(split(datum.date,'-')[0],split(datum.date,'-')[1],split(datum.date,'-')[2],datum.hr) ",
"as": "t"
}
],
"encoding": {
"x": {"field": "t", "type": "temporal", "title": "Time"},
"y": {"type": "quantitative", "axis": {"title": "Temp.[°C]"}}
},
"layer": [
{
"mark": {"type": "circle", "opacity": 0.75, "tooltip": true},
"encoding": {
"y": {"field": "temp", "title": "Temp."},
"color": {
"field": "temp",
"type": "quantitative",
"scale": {"domainMid": 0, "scheme": "viridis"},
"title": "[°C]"
}
}
}
]
}

Related

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

Is it possible to achieve this aggregation using vega/vega-lite?

I have a data list of this format
[
{"id": 100, "y": 28, "c":0},
{"id": 1, "y": 20, "c":1},
{"id": 2, "y": 43, "c":0},
{"id": 3, "y": 35, "c":1},
{"id": 4, "y": 81, "c":0},
{"id": 5, "y": 10, "c":1},
{"id": 6, "y": 19, "c":0},
{"id": 7, "y": 15, "c":1},
{"id": 8, "y": 52, "c":0},
{"id": 9, "y": 48, "c":1}
]
My goal is to achieve sum aggregation of x and y fields for all documents excluding id=100, then to subtract this result of aggregation from x and y values of document with id=100, and display this result as text type mark.
I've tried the following :
{
$schema: https://vega.github.io/schema/vega/v3.0.json
title: Sum amount Per id
data: [
{
"name": "table",
"values": [
{"id": 100, "y": 28, "c":0},
{"id": 1, "y": 20, "c":1},
{"id": 2, "y": 43, "c":0},
{"id": 3, "y": 35, "c":1},
{"id": 4, "y": 81, "c":0},
{"id": 5, "y": 10, "c":1},
{"id": 6, "y": 19, "c":0},
{"id": 7, "y": 15, "c":1},
{"id": 8, "y": 52, "c":0},
{"id": 9, "y": 48, "c":1}
]
transform: [
{
type: aggregate
ops: ["sum","sum"]
fields: ["c", "y"]
as: ["sumc","sumy"]
}
]
}
]
marks: [
{
type: text
from: {data: "table"}
encode: {
update: {
text: {signal: "datum.sumc"}
align: {value: "center"}
baseline: {value: "middle"}
xc: {signal: "width/4"}
yc: {signal: "height/2"}
fontSize: {signal: "min(width/10, height)/1.3"}
}
}
}
{
type: text
from: {data: "table"}
encode: {
update: {
text: {signal: "datum.sumy"}
align: {value: "center"}
baseline: {value: "middle"}
xc: {signal: "width*3/4"}
yc: {signal: "height/2"}
fontSize: {signal: "min(width/10, height)/1.3"}
}
}
}
]
}
Please help me with how to achieve the subtraction from id=100
I was able to solve this using the JoinAggregate transform of Vega by adding the aggregation values as additional columns to the data set and then filtering to get a single row with the desired values!
{
"$schema": "https://vega.github.io/schema/vega/v3.0.json",
"title": "Sum amount Per id",
"data": [
{
"name": "table",
"values": [
{"id": 100, "y": 2800, "c": 1000},
{"id": 1, "y": 20, "c": 1},
{"id": 2, "y": 43, "c": 0},
{"id": 3, "y": 35, "c": 1},
{"id": 4, "y": 81, "c": 0},
{"id": 5, "y": 10, "c": 1},
{"id": 6, "y": 19, "c": 0},
{"id": 7, "y": 15, "c": 1},
{"id": 8, "y": 52, "c": 0},
{"id": 9, "y": 48, "c": 1}
],
"transform": [
{
"type": "joinaggregate",
"ops": ["sum", "sum"],
"fields": ["c", "y"],
"as": ["sumc", "sumy"]
},{
"type":"filter"
"expr":"datum.id==100"
}
]
}
],
"marks": [
{
"type": "text",
"from": {"data": "table"},
"encode": {
"update": {
"text": {"signal": "-datum.sumc+datum.c*2"},
"align": {"value": "center"},
"baseline": {"value": "middle"},
"xc": {"signal": "width/4"},
"yc": {"signal": "height/2"},
"fontSize": {"signal": "min(width/10, height)/1.3"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"update": {
"text": {"signal": "datum.y-datum.sumy+datum.y"},
"align": {"value": "center"},
"baseline": {"value": "middle"},
"xc": {"signal": "width*3/4"},
"yc": {"signal": "height/2"},
"fontSize": {"signal": "min(width/10, height)/1.3"}
}
}
}
]
}

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

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