Vega-Lite Calculated Scale domainMax - vega-lite

I'm trying to calculate a value for domainMax on the Y-axis scale. I tried the following example where I want the Y-axis domainMax to be one greater than the maximum value in the dataset field named "value". The example produces the error 'Unrecognized signal name: "domMax"'. How can I get it to work?
{
"data": {
"values": [
{"date": "2021-03-01T00:00:00", "value": 1},
{"date": "2021-04-01T00:00:00", "value": 3},
{"date": "2021-05-01T00:00:00", "value": 2}
]
},
"transform": [
{ "calculate": "max(datum.value)+1","as": "domMax"}
],
"mark": "line",
"encoding": {
"x": {
"field": "date",
"type": "temporal"
},
"y": {"field": "value", "type": "quantitative",
"scale": {"domainMax": {"expr": "domMax"}}
}
}
}

This transform
"transform": [
{ "calculate": "max(datum.value)+1","as": "domMax"}
]
adds a new column to your data set - it does not create a new signal. You can check that in the editor. Go to the DataViewer tab and select data_0 from the drop down. Can you see the new domMax column?
Signals are a different thing entirely - have a look here in the documentation. Note that the link points to Vega, not Vega-Lite. (Vega-Lite specifications are compiled to Vega.)
Vega-Lite does not let you declare signals; you declare parameters instead. Here is another example using the domMax parameter. Vega-Lite parameters are translated to Vega signals.
It looks like you are trying to derive the value of your parameter/signal from the data. I am not sure you can do that in Vega-Lite.
On the other hand it's very easy in Vega. For example you could use the extent transform:
https://vega.github.io/vega/docs/transforms/extent/
Side comment - while Vega specifications are more verbose you can sometimes find their primitives simpler and a good way to understand how the visualisation works. (You can see compiled Vega in the editor.)

I tried to get a custom domain based on the data but hit the same limitations as you did.
In my case, I update the data from the outside a bit like the streaming example. I compute the domain from the outside and modify them in the visualization with params. This is quite easy as vega-lite params are exposed as vega signals.
This is the gist of the layout:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"params": [
{
"name": "lowBound",
"value": -10
},
{
"name": "highBound",
"value": 100
}
],
../..
"vconcat": [
{
"name": "detailed",
../..
"layer": [
{
../..
"mark": "line",
"encoding": {
"y": {
"field": "value",
"title": "Temperature",
"type": "quantitative",
"scale": {
"domainMin": {
"expr": "lowBound"
},
"domainMax": {
"expr": "highBound"
}
}
},
...
The lowBound and highBound are dynamically changed through vega signals. I change them with the regular JS API.

You can add a param to pan and zoom in case your hard coded values are less than ideal.
"params": [{"name": "grid", "select": "interval", "bind": "scales"}],
Open the Chart in the Vega Editor

Related

Is it possible to transform json key into its own data field in vega-lite?

I'm trying to build a chart from live json data but the format has the date data as the key for other nested data, the essential structure is:
{
"Meta": {
"Frequency": "Monthly",
"Time zone": "EST"
},
"Monthly data": {
"2022-01-01": {
"valueA": "13.44",
"valueB": "97.68"
},
"2021-12-01": {
"valueA": "11.39",
"valueB": "99.81"
},
"2021-11-01": {
"valueA": "12.31",
"valueB: "93.56"
},
"2022-10-01": {
"valueA": "15.42",
"valueB": "98.54"
}
}}
I'm trying to get into a format where i can encode the date on the x-axis, but can't as there is no column name/key and it isn't an array so cannot flatten. Then would be looking to encode any normal nested field (eg valueA) on the y-axis, but can't find any documentation or examples on this specific case. I don't need any information in the metadata part so can be ignored.
The only similar comment on this I've found is https://github.com/vega/vega/issues/1360, I can get this to work as a test but typing out each monthly date to map of course removes the benefit of live data and wouldn't allow high-frequency data.
Is there a way for this to be mapped automatically?
No, I don't believe this is currently possible. You could potentially do it with the flatten transform if there were a vega expression for extracting keys from an object, but support for this has not yet been added to vega expressions (see https://github.com/vega/vega/issues/3207 for a similar request).
Unfortunately, I believe the best you can do currently is use the fold transform while specifying the keys explicitly. For example:
{
"data": {
"values": {
"2022-01-01": {"valueA": "13.44", "valueB": "97.68"},
"2021-12-01": {"valueA": "11.39", "valueB": "99.81"},
"2021-11-01": {"valueA": "12.31", "valueB": "93.56"},
"2022-10-01": {"valueA": "15.42", "valueB": "98.54"}
}
},
"transform": [
{
"fold": ["2021-11-01", "2021-12-01", "2022-01-01", "2022-10-01"],
"as": ["date", "value"]
},
{"calculate": "datum.value.valueA", "as": "valueA"},
{"calculate": "datum.value.valueB", "as": "valueB"}
],
"mark": "bar",
"encoding": {
"y": {"field": "date"},
"x": {"field": "valueA"},
"x2": {"field": "valueB"}
}
}

How to draw vertical lines based on a different quantity than that for the x channel in charts by row channel?

I'd like to have multiple time series drawn by row channel ("field": "PLATFORM"), x channel: ("field": "estimating-date-time"), and y channel ("field": "eta-variance").
Besides the lines of time series, I'd like to draw a vertical line at x = arrvial-time which is another field, conditioned by the value of "PLATFORM".
The following is a working example of the charts except the desirable vertical line in each chart:
vega-lite for multiple time series
Below is the desired effect with manual illustration:
My question is how to add the vertical line for each chart to the specifications?
The challenge to me is that the field "arrival-time" from which the value used to draw the vertical line is not the same as the chart's x channel "estimating-data-time". I've found examples of drawing such a line using a value related to the same x channel.
You can do this by nesting a layer specification within a facet operator; something like this (open in editor):
{
"facet": {"row": {"field": "PLATFORM"}},
"spec": {
"height": 80,
"width": 300,
"layer": [
{
"mark": "line",
"encoding": {
"x": {"field": "estimating-date-time", "type": "temporal"},
"y": {"field": "ETA-variance", "type": "quantitative"}
}
},
{
"mark": "rule",
"encoding": {"x": {"field": "arrival-time", "type": "temporal"}}
}
]
},
"data": {...}
}

How to draw a line in a line chart in vega-lite?

I have a curve plotted from index
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.4.json",
"title": {
"text": "Receiver Operating Characteristics - Area Under Curve",
"anchor": "middle",
"fontSize": 16,
"frame": "group",
"offset": 4
},
"data": {
"url" : {
"%context%": true,
"index": "roccurve_index2",
"body": {
"size":10000,
"_source": ["lr_fpr", "lr_tpr"],
}
}
"format": {"property": "hits.hits"},
},
"mark": {
"type": "line",
"point": true
},
"encoding": {
"x": {"field": "_source.lr_fpr", "type": "quantitative", "title":"False Positive Rate"},
"y": {"field": "_source.lr_tpr", "type": "quantitative", "title":"True Positive Rate"}
}
}
the plot looks like
Now i need to draw a base line for base model between 0 and 1 like
Is this possible, and make that as dashed line with legend showing names as Base Model, RF Model
Yes, it is possible using Layered Views.
I'll use the Line Chart example to modify and add another line that's also dashed.
Original chart:
https://vega.github.io/editor/#/examples/vega-lite/line
Here's the modified chart, I used explicit values for the straight line:
https://vega.github.io/editor/#/gist/152fbe5f986ba78e422bb3430628f010/spec.json
Layer Solution
When you use layered view, you can lay multiple lines in the same chart and same x and y axis
"layer" : [
{
//mark #1
},
{
//mark #2
}
]
Dashed Line
Can be achieved using strokeDashproperty. See this example: Line chart with varying stroke dash

What is wrong on inline values?

The "line chart" demo works fine, and is expressed in javascript, as in getting_started.html.
... but when I replace "data" field from URL to inline values, it shows only the axys, no chart into.
It works: "data":{"url":"https://vega.github.io/vega-lite/examples/data/stocks.csv"},
It not works:
var vlSpec = {
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Google's stock price over time.",
"data": {"values": [
{"symbol":"MSFT","date":"Jan 1 2000","price":39.81},
{"symbol":"MSFT","date":"Feb 1 2000","price":36.35},
{"symbol":"MSFT","date":"Mar 1 2000","price":43.22},
{"symbol":"MSFT","date":"Apr 1 2000","price":28.37},
{"symbol":"MSFT","date":"May 1 2000","price":25.45}
]},
"transform": [{"filter": "datum.symbol==='GOOG'"}],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
};
There are an error at console, that not make sense:
WARN Infinite extent for field "date": [Infinity, -Infinity]
Your specification only contains rows with symbol="MSFT". It also contains a filter transform, {"filter": "datum.symbol==='GOOG'"}, which removes all rows except those with symbol="GOOG". The result is there is no data left to plot.
The warning you see comes from the fact that axis extent is determined from the data, and when there is no data, the extent is left at [-Infinity, Infinity].
If you remove or modify this filter statement, the chart will work. For example:
vlSpec = {
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Google's stock price over time.",
"data": {"values": [
{"symbol":"MSFT","date":"Jan 1 2000","price":39.81},
{"symbol":"MSFT","date":"Feb 1 2000","price":36.35},
{"symbol":"MSFT","date":"Mar 1 2000","price":43.22},
{"symbol":"MSFT","date":"Apr 1 2000","price":28.37},
{"symbol":"MSFT","date":"May 1 2000","price":25.45}
]},
"transform": [{"filter": "datum.symbol==='MSFT'"}],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
};
The result looks like this (Open the Chart in the Vega Editor):
Need only to comment the "magic line"
// "transform": [{"filter": "datum.symbol==='GOOG'"}],
Please explain! This is a Wiki answer
According to the Vega docs for the Date type, the date needs to be a valid Javascript Date object or timestamp.
A valid JavaScript Date object or timestamp. As JSON does not support date values natively, within a Vega specification a date-time value can be expressed either as a numeric timestamp (the number of milliseconds since the UNIX epoch, as produced by the Date.getTime() method) or using a signal expression (such as {"signal": "datetime(2001, 2, 3)"})

Is it possible to use facets and repeat operator for histograms?

I want to combine facet operators (row, column) along with the repeat operator to create 'small multiple' charts that display different data variables. This works for some types of charts (e.g. simple bar charts) but not others (i.e. histograms). For example, below I have modified the 'Horizontally repeated charts' example (https://vega.github.io/vega-lite/examples/repeat_histogram.html).
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"repeat": {"column": ["Horsepower","Miles_per_Gallon", "Acceleration"]},
"spec": {
"data": {"url": "data/cars.json"},
"mark": "bar",
"encoding": {
"row":{"field":"Origin", "type":"nominal"},
"x": {
"field": {"repeat": "column"},
"bin": true,
"type": "quantitative"
},
"y": {"aggregate": "count","type": "quantitative"}
}
}
}
I expect three rows, with each row showing histograms of cars from different countries. However, this code results in the error :
'Error: Undefined data set name: "scale_child_Miles_per_Gallon_child_main"'
I'm reasonably sure that this worked with Vega-Lite v2. Is there some reason that the aggregate / bin operator can't work with a combination of facets and repeats?