I'm trying to plot something like a trail mark but where I can map the line colour instead of the line size. Is that possible? So far I haven't been able to achieve it.
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Google's stock price over time.",
"data": {"url": "data/stocks.csv"},
"transform": [
{"filter": "datum.symbol==='GOOG'"},
{"calculate": "datum.price>400", "as": "good"}
],
"mark": "trail",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"},
"size": {"field": "good", "type": "nominal"}
}
}
This is when using size with a trail mark.
This if I map to color.
Lines cannot be multiple colors in Vega-Lite, but you can use a color encoding along with an impute transform to change the color of different sections of the line (vega editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Google's stock price over time.",
"data": {"url": "data/stocks.csv"},
"transform": [
{"filter": "datum.symbol==='GOOG'"},
{"calculate": "datum.price>400", "as": "good"}
],
"mark": "line",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative", "impute": {"value": null}},
"color": {"field": "good", "type": "nominal"}
}
}
Unfortunately this leaves breaks in the line; you can get around this by creating a background layer like this (vega editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Google's stock price over time.",
"data": {"url": "data/stocks.csv"},
"transform": [
{"filter": "datum.symbol==='GOOG'"},
{"calculate": "datum.price>400", "as": "good"}
],
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative", "impute": {"value": null}}
},
"layer": [
{"mark": "line"},
{
"mark": "line",
"encoding": {"color": {"field": "good", "type": "nominal"}}
}
]
}
Edit: if you're using Altair, the equivalent would be something like this:
import altair as alt
from vega_datasets import data
alt.layer(
alt.Chart().mark_line(),
alt.Chart().mark_line().encode(color='good:N'),
data=data.stocks.url
).transform_filter(
'datum.symbol==="GOOG"',
).transform_calculate(
good="datum.price>400"
).encode(
x='date:T',
y=alt.Y('price:Q', impute={'value': None})
)
Related
I'm new to WebStorm and vega/vegalite and I am working on creating a visual with different types of gasoline and their prices from 1996-2020.
I've been able to create a graph with all of the information, but it's pretty hard to discern anything.
I've been going over the Vega-Lite documentation and I see that that I can use tooltips to zoom into the graphic. I tried implementing it, but I don't think I quite understand the scope of some of the properties.
Could someone show me how they might approach this task? Or perhaps even recommend videos or websites that might help me better understand how to do?
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Area charts of stock prices, with an interactive overview and filtered detail views.",
"width": 720,
"height": 480,
"padding": 5,
"data": {
"name": "gas_prices",
"url": "data/testInfo.csv",
"format": {"type": "csv", "parse": {"A1": "number", "date": "date"}}
},
"repeat": {
"layer": ["A1","A2","A3","R1","R2","R3","M1","M2","M3","P1","P2","P3","D1"]
},
"spec": {
"mark": "line",
"encoding": {
"x": {
"timeUnit": "yearmonth",
"title": "Date",
"field": "date"
},
"y": {
"field": {"repeat":"layer"},
"title": "Gas Prices",
"type": "quantitative"
},
"color": {
"datum": {"repeat": "layer"},
"type": "nominal"
}
}
}
}
You can refer the documentation for tooltip, which says about the options available to enable tooltips on your chart.
Below is a sample config having default tooltip or refer editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"repeat": ["Horsepower", "Miles_per_Gallon", "Acceleration", "Displacement"],
"columns": 2,
"spec": {
"data": {"url": "data/cars.json"},
"mark": {"type": "bar", "tooltip": true},
"encoding": {
"x": {"field": {"repeat": "repeat"}, "bin": true},
"y": {"aggregate": "count"},
"color": {"field": "Origin"}
}
}
}
To have tooltips with some customizations, you can refer below code or editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"repeat": ["Horsepower", "Miles_per_Gallon", "Acceleration", "Displacement"],
"columns": 2,
"spec": {
"data": {"url": "data/cars.json"},
"mark": "bar",
"encoding": {
"tooltip": [
{"aggregate": "count", "title": "YAxis"},
{"field": {"repeat": "repeat"}, "title": "myXAxis"}
],
"x": {"field": {"repeat": "repeat"}, "bin": true},
"y": {"aggregate": "count"},
"color": {"field": "Origin"}
}
}
}
When add the strips as a new layer (in the 2-layers chart), stops to work: there are no visualization and a "WARN Cannot project a selection on encoding channel "y", which has no field".
The first two layer-definitions bellow was working fine when only two lines.
vglSpec.push(['#vis2a',{
$schema: vglVers,
data: {"url":"MyDataset1"},
// old "encoding": { x: {"field": "instant", "type": "temporal"} }
width:680,
layer: [
{
"mark": {"stroke": "#68C", "type": "line", "point": true},
"encoding": { x: {"field": "instant", "type": "temporal"}, "y": {
"field": "n_count",
"type": "quantitative"
}},
"selection": {"grid": {"type":"interval", "bind":"scales"}} //zoom
},
{
"mark": {"stroke": "red", "type": "line", "strokeOpacity": 0.4},
"encoding": { x: {"field": "instant", "type": "temporal"}, "y": {
"field": "instant_totmin",
"type": "quantitative"
}}
},
{
"mark": "rule",
"data": {"url":"MyDataset2"}, // little subset of instant of Dataset1
"encoding": {
"x": { "field": "instant", "type": "temporal"},
"color": {"value": "yellow"},
"size": {"value": 5}
},
//resolve:? x is same axis and the only visualization field
}
],
resolve: {"scale": {"y": "independent"}}
}]);
PS: only removed names and titles, all real script.
Emulating with dummy data: working fine!
Please click on the 3rd example of rule guide... And replace or adapt it for this VEGA-lite script:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {"url": "data/movies.json"},
"layer": [
{
"mark": "bar",
"encoding": {
"x": {"bin": true, "field": "IMDB_Rating", "type": "quantitative"},
"y": {"aggregate": "count", "type": "quantitative"}
}
},
{
"mark": "rule",
"data": {"values": [{"IMDB_Rating":3.5},{"IMDB_Rating":7.8}]},
"encoding": {
"x": { "field": "IMDB_Rating","type": "quantitative" },
"color": {"value": "yellow"},
"size": {"value": 4}
}
}
]
}
You're using an independent y-scale, and the y-scale of a rule mark with no y encoding is not well defined. The best way to address this is probably to combine the rule mark with one of the other layers, so it can use that y scale:
vglSpec.push(['#vis2a',{
$schema: vglVers,
data: {"url":"MyDataset1"},
// old "encoding": { x: {"field": "instant", "type": "temporal"} }
width:680,
layer: [
{
"mark": {"stroke": "#68C", "type": "line", "point": true},
"encoding": { x: {"field": "instant", "type": "temporal"}, "y": {
"field": "n_count",
"type": "quantitative"
}},
"selection": {"grid": {"type":"interval", "bind":"scales"}} //zoom
},
{
layer: [
{
"mark": {"stroke": "red", "type": "line", "strokeOpacity": 0.4},
"encoding": { x: {"field": "instant", "type": "temporal"}, "y": {
"field": "instant_totmin",
"type": "quantitative"
}}
},
{
"mark": "rule",
"data": {"url":"MyDataset2"}, // little subset of instant of Dataset1
"encoding": {
"x": { "field": "instant", "type": "temporal"},
"color": {"value": "yellow"},
"size": {"value": 5}
},
//resolve:? x is same axis and the only visualization field
}
]
}
],
resolve: {"scale": {"y": "independent"}}
}]);
(note, I've not actually tried this solution because you didn't include data in your question, but the approach should work).
This is a follow up from a previous question for which I built a test case in a (hopefully now public) notebook and noticed the following behavior:
At the end of the notebook, in the section bugs you will notice that y-axis of the max_precipitation of the layered chart using is clamped to 10.
I tried changing the domain but the bars do not go above 10.
Here the code example in vega-lite's editor reproduced below:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"title": "Top Months by Mean Precipitation",
"data": {"url": "data/seattle-weather.csv"},
"transform": [
{"timeUnit": "month", "field": "date", "as": "month_date"},
{
"aggregate": [
{"op": "mean", "field": "precipitation", "as": "mean_precipitation"},
{"op": "max", "field": "precipitation", "as": "max_precipitation"}
],
"groupby": ["month_date"]
},
{
"window": [{"op": "row_number", "as": "rank"}],
"sort": [{"field": "mean_precipitation", "order": "descending"}]
}
],
"encoding": {
"x": {
"field": "month_date",
"type": "ordinal",
"timeUnit": "month",
"title": "month (descending by max precip)",
"sort": {
"field": "max_precipitation",
"op": "average",
"order": "descending"
}
}
},
"layer": [
{
"mark": {"type": "bar"},
"encoding": {
"y": {
"field": "max_precipitation",
"type": "quantitative",
"title": "precipitation (mean & max)"
}
}
},
{
"mark": "tick",
"encoding": {
"y": {"field": "mean_precipitation", "type": "quantitative"},
"color": {"value": "red"},
"size": {"value": 15}
}
}
]
}
Please help me understand what I am doing wrong?
It appears that the precipitation column is being parsed as strings rather than as numbers. You can specify the parsing format for the column using :
"data": {
"url": "data/seattle-weather.csv",
"format": {"parse": {"precipitation": "number"}}
},
The result is here:
I have data as shown:
2021 43466.822 medium variant
2021 43510.982 high variant
2021 43416.407 low variant
2021 43468.429 constant fertility
2021 43580.45 instant replacement
And need to get chart:
https://image.prntscr.com/image/eBKqmOUsSa_6PBlomh5Erg.png
I have tried the transform fold option, but it does not help me. And making a lot of layers for that - will be a lot of code. Is there any smart way? Also I will need an legend like the one shown.
vegalite({
height:300,
autosize: "fit",
width:width,
title: {text:"Ukraine Population Prospects",
subtitle:"Total population, million"
},
data: {
url:"https://gist.githubusercontent.com/turiy/005f2ce11637fefcde8e9d6efdb0c2e6/raw/19e67bb3a6d63e7fd9f49a596e5d24404469bd63/population_prospects.csv"},
transform: [{"calculate": "datum.population/1000", "as": "population"},{fold:["medium variant","high variant", "low variant", "constant fertility","instant replacement", "momentum", "zero migration", "constant mortality", "no change"]}],
layer: [
{ mark: "line",
encoding:{
"x": {
"timeUnit": "utcyear",
"field": "year",
"type": "temporal",
"axis": {
"values":[1950,1991,2020,2100],
"domain": false,
"gridDash": {"value": [1,1]}
}
},
"y": {
"field": "population",
"type": "quantitative",
"scale": {"domain": [15,55]},
"axis": {
"domain": false ,
"gridDash": {"value": [1,1]}
}
}
},
color: {"value":"#0000ff"},
transform:[{filter:{"timeUnit": "utcyear", "field": "year", "range": [1950, 2020]}}]
},
{
mark: "line",legend:{title:"low variant"},
encoding:{
x: {
"timeUnit": "utcyear",
"field": "year",
"type": "temporal",
"axis": {
"values":[1950,1991,2020,2100],
"domain": false,
"gridDash": {"value": [1,1]}}
},
y: {
"field": "population",
"type": "quantitative",
"scale": {"domain": [15,55]},
"axis": {
"domain": false ,
"gridDash": {"value": [1,1]}
}
},
legends:{
"orient": "top-right",
"stroke": "color",
"title": "Origin",
"encode": {
"symbols": {
"update": {
"fill": {"value": ""},
"strokeWidth": {"value": 2},
"size": {"value": 64}
}
}
}
},
color: {"field": "key", "type":"nominal"}
},
transform:[{filter:{"timeUnit": "year", "field": "year", "range": [2020, 2100]}},
{filter:{field:"type", "equal":"low variant"}}]
}
]})
And I am getting like this https://image.prntscr.com/image/3Y9WNk4SQzGYWDr2JKWV9A.png
If your variants are listed by name in a column as in your example dataset, you can use a detail encoding to split them into different lines (vega editor link):
{
"data": {
"url": "https://gist.githubusercontent.com/turiy/005f2ce11637fefcde8e9d6efdb0c2e6/raw/19e67bb3a6d63e7fd9f49a596e5d24404469bd63/population_prospects.csv"
},
"mark": "line",
"encoding": {
"detail": {"type": "nominal", "field": "type"},
"x": {"type": "quantitative", "field": "year"},
"y": {"type": "quantitative", "field": "population"}
}
}
If you use color rather than detail, each line will be a different color and a legend will be included.
To add labels at the right side of the chart, you can use a text mark with an aggregate transform; something like this:
{
"data": {
"url": "https://gist.githubusercontent.com/turiy/005f2ce11637fefcde8e9d6efdb0c2e6/raw/19e67bb3a6d63e7fd9f49a596e5d24404469bd63/population_prospects.csv"
},
"layer": [
{
"mark": "line",
"encoding": {
"detail": {"type": "nominal", "field": "type"},
"x": {"type": "quantitative", "field": "year"},
"y": {"type": "quantitative", "field": "population"}
}
},
{
"transform": [
{"filter": "datum.type != 'estimate'"},
{
"aggregate": [{"op": "argmax", "field": "year", "as": "rightmost"}],
"groupby": ["type"]
}
],
"mark": {"type": "text", "align": "left"},
"encoding": {
"text": {"type": "nominal", "field": "rightmost.type"},
"x": {"type": "quantitative", "field": "rightmost.year"},
"y": {"type": "quantitative", "field": "rightmost.population"}
}
}
],
"width": 400
}
Vega Editor link here
I've an overlay color change based on filter condition in a multi line chart. Got it working with single line here but 'red' overlay line(along with red dot) doesn't come up with this above multi-line example. Could anyone help me out?
Short answer: your chart is working, except the filtered values are not colored red.
The core issue is that encodings always supersede mark properties, as you can see in this simpler example: editor link
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"description": "A scatterplot showing horsepower and miles per gallons.",
"data": {"url": "data/cars.json"},
"mark": {"type": "point", "color": "red"},
"encoding": {
"x": {"field": "Horsepower", "type": "quantitative"},
"y": {"field": "Miles_per_Gallon", "type": "quantitative"},
"color": {"field": "Origin", "type": "nominal"},
"shape": {"field": "Origin", "type": "nominal"}
}
}
Notice that although we specify that the mark should have color red, this is overridden by the color encoding. This is by design within Vega-Lite, because encodings are more specific than properties.
Back to your chart: because you specify the color encoding in the parent chart, each individual layer inherits that color encoding, and those colors override the "color": "red" that you specify in the individual layers.
To make it do what you want, you can move the color encoding into the individual layers (and use a detail encoding to ensure the data are still grouped by that field). For example (editor link):
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"data": {...},
"width": 1000,
"height": 200,
"autosize": {"type": "pad", "resize": true},
"transform": [
{
"window": [{"op": "rank", "as": "rank"}],
"sort": [{"field": "dateTime", "order": "descending"}]
},
{"filter": "datum.rank <= 100"}
],
"layer": [
{
"mark": {"type": "line"},
"encoding": {
"color": {
"field": "name",
"type": "nominal",
"legend": {"title": "Type"}
}
}
},
{
"mark": {"type": "line", "color": "red"},
"transform": [
{
"as": "count",
"calculate": "if(datum.anomaly == true, datum.count, null)"
},
{"calculate": "true", "as": "baseline"}
]
},
{
"mark": {"type": "circle", "color": "red"},
"transform": [
{"filter": "datum.anomaly == true"},
{"calculate": "true", "as": "baseline"}
]
}
],
"encoding": {
"x": {
"field": "dateTime",
"type": "temporal",
"timeUnit": "hoursminutesseconds",
"sort": {"field": "dateTime", "op": "count", "order": "descending"},
"axis": {"title": "Time", "grid": false}
},
"y": {
"field": "count",
"type": "quantitative",
"axis": {"title": "Count", "grid": false}
},
"detail": {"field": "name", "type": "nominal"}
}
}