Customise vega-lite Line Graph Axis Labels - vega-lite

What I want to do is really simple, but I just can't seem to get it right. I have a feeling I'm going to be embarrassed by the answer!
I have a line graph with "attempt" along the x-axis and "grade" along the y-axis, with grade being a number between 0 and 100. I simply want to change the y-axis so that, instead of seeing the raw number, a grade is show, say with 0 - 20 representing "E", 20-40 being "D" etc up to "A" (80-100). How can I do that? I don't want to use discrete values because I want to visually show where within a grade boundary a grade falls. I'm not sure whether I yet want to simply display the grade bands on the line or put them in the middle of their ticks, but just getting somewhere with this would help a lot!
Here is what I've been working with in the vega-lite editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"data": {
"values": [
{
"attempt": 1,
"score": 30
},
{
"attempt": 2,
"score": 60
},
{
"attempt": 3,
"score": 75
},
{
"attempt": 4,
"score": 58
},
{
"attempt": 5,
"score": 67
}
]
},
"mark": {
"type": "line",
"color": "#22bc9a",
"point": {
"filled": false
}
},
"encoding": {
"x": {
"field": "attempt",
"type": "quantitative",
"axis": {
"grid": false,
"tickCount": 5,
"title": "Attempt"
}
},
"y": {
"field": "score",
"scale": {"domain": [0, 100]},
"type": "quantitative",
"axis": {
"tickCount": 5,
"title": "Grade"
}
},
"opacity": {"value": 0.3}
},
"config": {
"autosize": "fit",
"axis": {
"labelColor": "#bebec8",
"tickColor": "#bebec8",
"titleColor": "black",
"titleFontWeight": "normal",
"titleFontSize": 11,
"labelFont": "Helvetica",
"titleFont": "Helvetica",
"gridOpacity": 0.4,
"gridWidth": 1.5,
"domain": false
},
"view": {
"strokeWidth": 0
}
}
}
Thanks in advance.

What about something like this: I add a dataframe with the grade category, and use this to layer some text. I remove the labels of the axis and so the text acts as if it were the labels of the axis.
The chart looks like this, and here is a link to the editor:
Schema (Note that I did it with Python's Altair, so it may not be canonical Vega-lite, and I did not use your settings either, sorry about that):
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.6.0.json",
"config": {
"view": {
"height": 300,
"width": 400
}
},
"datasets": {
"data-1acee7c5d817865a529b53e022474ce8": [
{
"label": "E",
"x_min": 1,
"y_med": 10
},
{
"label": "D",
"x_min": 1,
"y_med": 30
},
{
"label": "C",
"x_min": 1,
"y_med": 50
},
{
"label": "B",
"x_min": 1,
"y_med": 70
},
{
"label": "A",
"x_min": 1,
"y_med": 90
}
],
"data-8e6359ea3034b8410708361bb10fafd5": [
{
"attempt": 1,
"score": 30
},
{
"attempt": 2,
"score": 60
},
{
"attempt": 3,
"score": 75
},
{
"attempt": 4,
"score": 58
},
{
"attempt": 5,
"score": 67
}
]
},
"layer": [
{
"data": {
"name": "data-1acee7c5d817865a529b53e022474ce8"
},
"encoding": {
"text": {
"field": "label",
"type": "ordinal"
},
"x": {
"field": "x_min",
"scale": {
"zero": false
},
"type": "quantitative"
},
"y": {
"axis": {
"labels": false,
"tickCount": 5,
"ticks": false
},
"field": "y_med",
"type": "quantitative"
}
},
"mark": {
"dx": -15,
"dy": 8,
"size": 15,
"type": "text"
}
},
{
"data": {
"name": "data-8e6359ea3034b8410708361bb10fafd5"
},
"encoding": {
"x": {
"axis": {
"tickCount": 5
},
"field": "attempt",
"title": "Attempt",
"type": "quantitative"
},
"y": {
"field": "score",
"scale": {
"domain": [
0,
100
]
},
"title": "Grade",
"type": "quantitative"
}
},
"mark": {
"point": true,
"type": "line"
}
}
]
}
Using a slighly modified dataframe for the categories (with x_max, y_min and y_max added), you can add another layer with colored rectangles, that can help read the values:
Here is a link to the editor
And here is the schema
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.6.0.json",
"config": {
"view": {
"height": 300,
"width": 400
}
},
"datasets": {
"data-1acee7c5d817865a529b53e022474ce8": [
{
"label": "E",
"x_min": 1,
"y_med": 10
},
{
"label": "D",
"x_min": 1,
"y_med": 30
},
{
"label": "C",
"x_min": 1,
"y_med": 50
},
{
"label": "B",
"x_min": 1,
"y_med": 70
},
{
"label": "A",
"x_min": 1,
"y_med": 90
}
],
"data-39ffbda2b5d5fe96de84d9e308d920ff": [
{
"label": "E",
"x_max": 5,
"x_min": 1,
"y_max": 20,
"y_med": 10,
"y_min": 0
},
{
"label": "D",
"x_max": 5,
"x_min": 1,
"y_max": 40,
"y_med": 30,
"y_min": 20
},
{
"label": "C",
"x_max": 5,
"x_min": 1,
"y_max": 60,
"y_med": 50,
"y_min": 40
},
{
"label": "B",
"x_max": 5,
"x_min": 1,
"y_max": 80,
"y_med": 70,
"y_min": 60
},
{
"label": "A",
"x_max": 5,
"x_min": 1,
"y_max": 100,
"y_med": 90,
"y_min": 80
}
],
"data-8e6359ea3034b8410708361bb10fafd5": [
{
"attempt": 1,
"score": 30
},
{
"attempt": 2,
"score": 60
},
{
"attempt": 3,
"score": 75
},
{
"attempt": 4,
"score": 58
},
{
"attempt": 5,
"score": 67
}
]
},
"layer": [
{
"data": {
"name": "data-39ffbda2b5d5fe96de84d9e308d920ff"
},
"encoding": {
"color": {
"field": "label",
"scale": {
"scheme": "greenblue"
},
"type": "ordinal"
},
"x": {
"field": "x_min",
"scale": {
"zero": false
},
"title": "Attempt",
"type": "quantitative"
},
"x2": {
"field": "x_max",
"type": "quantitative"
},
"y": {
"axis": null,
"field": "y_min",
"type": "quantitative"
},
"y2": {
"field": "y_max",
"type": "quantitative"
}
},
"mark": "rect"
},
{
"data": {
"name": "data-1acee7c5d817865a529b53e022474ce8"
},
"encoding": {
"text": {
"field": "label",
"type": "ordinal"
},
"x": {
"field": "x_min",
"scale": {
"zero": false
},
"type": "quantitative"
},
"y": {
"axis": {
"labels": false,
"tickCount": 5,
"ticks": false
},
"field": "y_med",
"type": "quantitative"
}
},
"mark": {
"dx": -15,
"dy": 8,
"size": 15,
"type": "text"
}
},
{
"data": {
"name": "data-8e6359ea3034b8410708361bb10fafd5"
},
"encoding": {
"x": {
"axis": {
"tickCount": 5
},
"field": "attempt",
"title": "Attempt",
"type": "quantitative"
},
"y": {
"field": "score",
"scale": {
"domain": [
0,
100
]
},
"title": "Grade",
"type": "quantitative"
}
},
"mark": {
"point": true,
"type": "line"
}
}
]
}

To get it working, I first had to change the encoding of the x and y axis to be ordinal. Then I mapped your input data values to letter grades before creating the schema:
//replace every score value with correct letter grade
values.forEach(datapoint => {
if(datapoint.score > 90) {
datapoint.score = "A";
} else if(datapoint.score > 80) {
datapoint.score = "B";
} else if (datapoint.score > 70) {
//so on...
}
});
Here is a working example in the vega-lite editor:
Line Chart with Ordinal Values
Here is the schema:
{
"$schema": "https://vega.github.io/schema/vega-lite/v3.json",
"data": {
"values": [
{
"attempt": 1,
"score": "F"
},
{
"attempt": 2,
"score": "D"
},
{
"attempt": 3,
"score": "C"
},
{
"attempt": 4,
"score": "F"
},
{
"attempt": 5,
"score": "D"
}
]
},
"mark": {
"type": "line",
"color": "#22bc9a",
"point": {
"filled": false
}
},
"encoding": {
"x": {
"field": "attempt",
"type": "ordinal",
"axis": {
"title": "Attempt"
}
},
"y": {
"field": "score",
"type": "ordinal",
"axis": {
"title": "Grade"
}
},
"opacity": {"value": 0.3}
},
"config": {
"autosize": "fit",
"axis": {
"labelColor": "#bebec8",
"tickColor": "#bebec8",
"titleColor": "black",
"titleFontWeight": "normal",
"titleFontSize": 11,
"labelFont": "Helvetica",
"titleFont": "Helvetica",
"gridOpacity": 0.4,
"gridWidth": 1.5
},
"view": {
"strokeWidth": 0
}
}
}

Related

Vega bar line chart opacity issue

In Vega Barline chart, I am looking help, when mouseover on Bar chart, line chart should be blur but all bar should be with opacity 1, similar when mouseover on line chart, bar chart should be blur.
In Vega Barline chart, I am looking help, when mouseover on Bar chart, line chart should be blur but all bar should be with opacity 1, similar when mouseover on line chart, bar chart should be blur.
I tried with below JSON
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"background": "transparent",
"width": 600,
"height": 300,
"style": "linear",
"data": [
{ "name": "barlineChart_store" },
{ "name": "barChart_store" },
{ "name": "lineChart_store" },
{
"name": "source_0",
"values": [ {
"year": 2013,
"value": 10
},
{
"year": 2014,
"value": 19
},
{
"year": 2015,
"value": 33
},
{
"year": 2016,
"value": 74
},
{
"year": 2017,
"value": 87
},
{
"year": 2018,
"value": 13
}, {
"year": 2019,
"value": 110
} ,
{
"year": 2020,
"value": 40
},
{
"year": 2021,
"value": 50
},{
"year": 2022,
"value": 49
}]
},
{
"name": "source_2",
"values": [ {
"year": 2013,
"value": 279670000
},
{
"year": 2014,
"value": 1017789660
},
{
"year": 2015,
"value": 4604761843
},
{
"year": 2016,
"value": 1829007526
},
{
"year": 2017,
"value": 21831592682
},
{
"year": 2018,
"value": 9236173024
},{
"year": 2019,
"value": 9848990024
},{
"year": 2020,
"value": 13365764829
},{
"year": 2021,
"value": 27294260073
},{
"year": 2022,
"value": 9982818889
}]
},
{
"name": "data_0",
"source": "source_0",
"transform": [
{
"type": "formula",
"expr": "timeParse(datum[\"year\"],'%Y')",
"as": "year",
},
{
"field": "year",
"type": "timeunit",
"units": ["year"],
"as": ["year_year", "year_year_end"],
},
{
"type": "stack",
"groupby": ["year_year"],
"field": "value",
"sort": { "field": [], "order": [] },
"as": ["value_start", "value_end"],
"offset": "zero",
},
{
"type": "filter",
"expr": "isValid(datum[\"value\"]) && isFinite(+datum[\"value\"])",
},
],
},
{
"name": "data_1",
"source": "source_2",
"transform": [
{
"type": "formula",
"expr": "timeParse(datum[\"year\"],'%Y')",
"as": "year",
},
{
"field": "year",
"type": "timeunit",
"units": ["year"],
"as": ["year_year", "year_year_end"],
},
],
},
{
"name": "data_2",
"source": "source_2",
"transform": [
{
"type": "formula",
"expr": "timeParse(datum[\"year\"],'%Y')",
"as": "year",
},
{
"field": "year",
"type": "timeunit",
"units": ["year"],
"as": ["year_year", "year_year_end"],
},
],
},
{
"name": "data_3",
"source": "data_2",
"transform": [
{
"type": "filter",
"expr": "isValid(datum[\"value\"]) && isFinite(+datum[\"value\"])",
},
],
},
],
"marks": [
{
"type": "group",
"name": "concat_0_group",
"signals": [
{
"name": "mouse__move",
"on": [
{
"events": [
{
"source": "scope",
"type": "mouseover",
},
],
"update":
"datum && item().mark.marktype !== \"group\" ? {unit: \"concat_0\", fields: recentTransaction_name, values: [(item().isVoronoi ? datum.datum : datum)[\"value\"]]} : null",
"force": true,
},
{
"events": [{ "source": "view", "type": "mouseout" }],
"update": "null",
},
],
},
{
"name": "recentTransaction_name",
"value": [{ "type": "E", "field": "value" }],
},
{
"name": "updated_barlinechart",
"on": [
{
"events": { "signal": "mouse__move" },
"update": "modify(\"barlineChart_store\", mouse__move, true)",
},
],
},
{
"name": "updated_linechart",
"on": [
{
"events": { "signal": "mouse__move" },
"update": "modify(\"lineChart_store\", mouse__move, true)",
},
],
},
{
"name": "updated_barchart",
"on": [
{
"events": { "signal": "mouse__move" },
"update": "modify(\"barChart_store\", mouse__move, true)",
},
],
},
],
"marks": [
{
"name": "bar",
"type": "rect",
"style": ["rect"],
"from": {"data": "data_0"},
"encode": {
"update": {
"fill": { "value": "#b14891" },
"description": {
"signal": "\"start (year): \" + (timeFormat(datum[\"year_start\"], timeUnitSpecifier([\"year\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; end (year): \" + (timeFormat(datum[\"year_end\"], timeUnitSpecifier([\"year\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})))"
},
"x": { "scale": "x", "field": "year_year" },
"width": { "scale": "x", "band": 1 },
"y": { "scale": "layer_0_y", "field": "value_end",
},
"y2": { "scale": "layer_0_y", "field": "value_start" },
"tooltip": {
"signal": "{'Value of Transactions': datum.value}",
},
"opacity": [
{
"test":
"(!length(data('barChart_store')) || vlSelectionTest('barChart_store', datum)) ",
"value": 1,
},
{ "value": 0.2 },
],
"fillopacity": [
{
"test":
"(length(data('barChart_store')) || vlSelectionTest('barChart_store', datum)) ",
"value": 1
},
{"value": 0.2}
],
},
"hover": {
"fillOpacity": {"value": 1}
}
}
},
{
"name": "line",
"type": "line",
"style": ["line"],
"from": { "data": "data_1" },
"encode": {
"update": {
"strokeWidth": { "value": 3 },
"stroke": { "value": "#35a4e8" },
"description": {
"signal":
"'year (year): ' + (timeFormat(datum['year_year'], '%Y'))",
},
"x": { "scale": "x", "field": "year_year", "band": 0.5 },
"y": { "scale": "layer_2_y", "field": "value" ,
},
"tooltip": {
"signal": "{'Value of Transactions': datum.value}",
},
"opacity": [
{
"test":
"(!length(data('barlineChart_store')) || vlSelectionTest('barlineChart_store', datum)) ",
"value": 1,
},
{ "value": 0.7 },
],
"hover": {
"fillOpacity": {"value": 1}
}
},
},
},
{
"name": "point",
"type": "symbol",
"style": ["point"],
"from": { "data": "data_1" },
"encode": {
"update": {
"fill": { "value": "#24242d" },
"stroke": { "value": "#35a4e8" },
"strokeWidth": { "value": 3.5 },
"size" : {"value": "100"},
"ariaRoleDescription": { "value": "point" },
"description": {
"signal":
"'year (year): ' + (timeFormat(datum['year_year'], '%Y'))",
},
"opacity": [
{
"test":
"(!length(data('barlineChart_store')) || vlSelectionTest('barlineChart_store', datum)) ",
"value": 1,
},
{ "value": 0.2 },
],
"x": { "scale": "x", "field": "year_year", "band": 0.5 },
"y": { "scale": "layer_2_y", "field": "value" },
"tooltip": {
"signal": "{'Value of Transactions': datum.value}",
},
},
},
}
],
},
],
"scales": [
{
"name": "x",
"type": "band",
"domain": {
"fields": [
{ "data": "data_0", "field": "year_year" },
{ "data": "data_1", "field": "year_year" },
{ "data": "data_2", "field": "year_year" },
],
"sort": true,
},
"range": [0, { "signal": "width" }],
"padding": 0.6,
},
{
"name": "layer_0_y",
"type": "linear",
"domain": { "data": "data_0", "fields": ["value_start", "value_end"] },
"range": [{ "signal": "height" }, 0],
"nice": true,
"zero": true,
},
{
"name": "layer_2_y",
"type": "linear",
"domain": {
"fields": [
{ "data": "data_2", "field": "value" },
],
},
"range": [{ "signal": "height" }, 0],
"nice": true,
"zero": true,
},
{
"name": "color",
"type": "ordinal",
"domain": ["Number of Transactions", "Value of Transactions"],
"range": ["#ca61aa", "#35a4e8"],
},
],
"axes": [
{
"scale": "x",
"orient": "bottom",
"grid": false,
"labelAngle": 0,
"format": "%Y",
"formatType": "time",
"labelBaseline": "top",
"labelFlush": true,
"labelOverlap": true,
"zindex": 0,
"labelPadding":10,
},
{
"scale": "layer_0_y",
"orient": "left",
"grid": true,
"labelOverlap": true,
"tickCount": { "signal": "ceil(height/80)" },
"zindex": 0,
"title":"Value",
"titleColor":"white",
"labelPadding":10,
},
{
"scale": "layer_2_y",
"orient": "right",
"grid": false,
"labelOverlap": true,
"tickCount": { "signal": "ceil(height/80)" },
"format":".2s",
"zindex": 0,
"title":"Amount",
"titleColor":"white",
"labelPadding":10,
},
],
"legends": [{ "labelColor": "#c4c4cd ", "fill": "color", "direction": "horizontal" ,"orient":"bottom",
"encode": {
"labels": {
"name": "category_legend_labels",
"interactive": true
},
"symbols": {
"name": "category_legend_symbols",
"interactive": true
},
"entries": {
"name": "category_legend_entries",
"interactive": true,
"update": {"fill": {"value": "transparent"}}
}
}}],
"config": { "axis": { "labelColor": "white", "title": "" ,"domain": false, "grid": false,"gridColor": "#979797", "ticks": false},"legend": { "columns":{"signal": "3"},"orient": "bottom",
"layout": {"bottom": {"anchor": "middle"}},
"labelColor": "white"}}
}

How to setup a month slider filter on Vega-Lite?

I've been trying to create a proportional symbol map with a month filter slider so that the bubbles change as I shift the slider. However, I've only been able to make a slider appear but the interactivity doesn't seem to work. I'd be very glad if someone could help me with this. This is the code I have so far. Thanks!
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"width": 800,
"height": 450,
"title": "Refugee Diaspora From Ukraine Post Invasion",
"projection": { "type": "equalEarth" },
"layer": [
{
"data": {
"url": "https://raw.githubusercontent.com/syedzubinhafiz/test_london/main/ne_110m.topojson.json",
"format": { "type": "topojson", "feature": "ne_110m_admin_0_countries" }
},
"mark": { "type": "geoshape", "fill": "lightgray", "stroke": "white" }
},
{
"data": {
"url": "https://raw.githubusercontent.com/syedzubinhafiz/test_london/main/combined.csv"
},
"mark": { "type": "circle" },
"params": [
{
"name": "Month Selection",
"value": 3,
"select": { "type": "point", "fields": ["month"] },
"bind": {
"month": { "input": "range", "min": 3, "max": 9, "step": 1 }
}
}
],
"transform": [
{
"timeUnit": "month",
"field": "date",
"as": "month"
},
{ "filter": { "field": "month", "gt": 3 } }
],
"encoding": {
"longitude": { "field": "centroid_lon", "type": "quantitative" },
"latitude": { "field": "centroid_lat", "type": "quantitative" },
"tooltip": [{ "field": "country" }, { "field": "individuals" }],
"size": {
"field": "individuals",
"type": "quantitative",
"title": "Immigrants"
},
"color": {
"field": "country",
"type": "nominal",
"scale": { "type": "linear", "scheme": "category10" }
}
}
}
]
}
`

How to filter data using a slider in vega-lite?

I am using the following code to plot a bubble plot using vega-lite. I want to transform values as I change the year value using the slider. But it's not working.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Drag the sliders to highlight points.",
"data": {
"url": "https://raw.githubusercontent.com/shre2398/InformationVisualization/main/gapminder.tsv",
"format": {
"type": "tsv"
}
},
"title": {
"text": "Gapminder Global Indicators",
"anchor": "middle",
"fontSize": 16,
"fontWeight": 700
},
"config": {
"axis": {
"titleFontSize": 13,
"titleFontWeight": "bold"
}
},
"params": [{
"name": "CurrentYear",
"value": [{"year": 1977}],
"select": {"type": "point", "fields": ["year"]},
"bind": {
"year": {"input": "range", "min": 1952, "max": 2007, "step": 5}
}
},{
"name": "View",
"select": "interval",
"bind": "scales"
}],
"width": 650,
"height": 400,
"mark": {
"type": "circle",
"opacity": 0.8,
"stroke": "white",
"strokeWidth": 1
},
"encoding": {
"x": {
"field": "gdpPercap",
"type": "quantitative",
"axis": {"grid": false},
"scale": {
"type": "log",
"base": 10
}
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"axis": {"title": ""}
},
"size": {
"field": "pop"
},
"color": {
"field": "continent"
}
}
}
If I add the following tranform block, it doesn't work.
"transform":[{"filter": {"param": "CurrentYear"}}]
I have already tried the following link :
https://vega.github.io/vega-lite/examples/interactive_query_widgets.html
It is because you are reading in your year column as strings, and then using a numerical selection to filter. You can see that the year values are strings in the "Data Viewer" tab. Reading in the data like this works with the transform filter you suggested above:
"data": {
"url": "https://raw.githubusercontent.com/shre2398/InformationVisualization/main/gapminder.tsv",
"format": {
"type": "tsv",
"parse": {"year": "number"}
}
}

vega lite - persist null date/time in chart

How do I persist the null in the data on visualization with vega chart while rendering the date/time for data the timestamp. Right now, it looks like null data is getting passed as default time of 04:00
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"x": null,
"y": "recoPU8F3Asuc8t3n"
},
{
"x": "2017-06-02T07:00:00.000Z",
"y": "reco056sZzsAd7qVp"
},
{
"x": null,
"y": "reclQZbw7CiAegm1f"
},
{
"x": "2017-07-14T07:00:00.000Z",
"y": "recAzUhUdekIdkSVt"
},
{
"x": null,
"y": "rec0NHCpaRDP9W1pd"
},
{
"x": null,
"y": "recPYz3QNpXgrmBVy"
}
]
},
"config": {
"range": {
"category": [
"#46bfdd"
]
},
"legend": {
"disable": false,
"labelColor": "#333",
"labelFontSize": 11,
"symbolSize": 30,
"rowPadding": 4,
"symbolType": "circle",
"symbolStrokeWidth": 0,
"titleColor": "#666666",
"titleFontSize": 11,
"titlePadding": 10,
"titleFontWeight": 500,
"orient": "right"
},
"axisY": {
"tickMinStep": 1,
"format": "~s",
"formatType": "number"
},
"axis": {
"domainColor": "#E8E8E8",
"gridColor": "#E8E8E8",
"tickColor": "#E8E8E8",
"grid": true,
"gridWidth": 1,
"labelColor": "#666666",
"labelFontSize": 11,
"labelLimit": 180,
"titleColor": "#999999",
"tickSize": 16,
"titleFontSize": 13,
"titlePadding": 10,
"titleFontWeight": 400,
"labelPadding": 4,
"titleLimit": 180
},
"autosize": {
"type": "fit",
"contains": "padding"
},
"axisLeft": {
"labelFontSize": 11,
"labelColor": "#999999",
"labelLimit": 180,
"titleFontSize": 13,
"titleFontWeight": 400,
"titleLimit": 180
},
"style": {
"label": {
"align": "left",
"baseline": "middle",
"dx": 4
},
"cell": {
"stroke": "transparent"
}
}
},
"mark": {
"type": "bar",
"width": {
"band": 0.7
},
"tooltip": true,
"cornerRadiusEnd": 3,
"cursor": "pointer",
"color": "#4787cd"
},
"params": [
{
"name": "highlight",
"select": {
"type": "point",
"on": "mouseover"
}
},
{
"name": "select",
"select": "point"
}
],
"encoding": {
"x": {
"field": "x",
"type": "nominal",
"axis": {
"labelAngle": -90,
"format": "%I:%M",
"formatType": "time",
"title": "Reservation On"
},
"sort": {
"encoding": "x",
"order": "ascending"
},
"timeUnit": "hoursminutes"
},
"y": {
"field": "y",
"type": "quantitative",
"aggregate": "count",
"axis": {
"title": "Number of records"
}
},
"tooltip": [
{
"field": "x",
"title": "Reservation On",
"format": "%I:%M",
"formatType": "time",
"timeUnit": "hoursminutes"
},
{
"field": "y",
"type": "quantitative",
"aggregate": "count",
"title": "Number of records"
}
],
"fillOpacity": {
"condition": [
{
"param": "select",
"value": 1
}
],
"value": 0.3
},
"strokeWidth": {
"condition": [
{
"param": "select",
"empty": false,
"value": 2
},
{
"param": "highlight",
"empty": false,
"value": 1
}
],
"value": 0
}
},
"transform": [
],
"height": 372,
"width": 536
}
One way to do this is by replacing your "format" with an appropriate "labelExpr":
"axis": {
"labelAngle": -90,
"labelExpr": "isValid(datum.value) ? timeFormat(datum.value, '%I:%M') : 'null'",
"title": "Reservation On"
}

Axis label dissappear when adding zooming (Vega-Lite)

I try to show timeseries data as point charts with two x-axis labels (2 text marks as my main x-axis attribute should not be displayed), mainly one at the top and one at the bottom. This works with a layered approach but as soon as I add the zoomable parameter to the visual, the text mark for the axes labels disappear. Is there a way on how to solve this issue?
That's how the visual looks like - without adding the zooming feature:
Timeseries point visual with two measure attributes and top and bottom x-axis label
What I’ve tried so far
I tried to position the params at different positions in the code as I am also using a vertical rule but it did not work out.
I also tried to make use of the scale resolve but I was neither successful.
Within the resolve, I tried to make use of the labelBound axis information and set it to false.
Basically, here is the code that I am currently using
{
"data": {
"name": "dataset"
},
"encoding": {
"x": {
"field": "TIMESTAMP",
"timeUnit": "utcyearmonthdatehoursminutes",
"type": "ordinal",
"axis": {
"grid": false,
"title": null,
"orient": "bottom",
"labels": false
}
}
},
"vconcat": [
{
"hconcat": [
{
"layer": [
{
"transform": [
{
"fold": [
"ATTRIBUTE1",
"ATTRIBUTE2"
],
"as": [
"measure1",
"temp1"
]
}
],
"mark": {
"type": "point",
"filled": true,
"size": 20
},
"height": 150,
"width": 700,
"encoding": {
"x": {
"timeUnit": "utcyearmonthdatehoursminutes",
"field": "TIMESTAMP",
"type": "ordinal",
"axis": {
"title": null,
"labels": false,
"ticks": false
}
},
"y": {
"field": "temp1",
"type": "quantitative",
"axis": {
"title": null
},
"scale": {
"zero": false,
"domain": [
450,
490
]
}
},
"color": {
"field": "measure1",
"type": "nominal",
"legend": {
"title": "Measures",
"orient": "right"
}
},
"opacity": {
"condition": [
{
"param": "legendhighlight",
"value": 1,
"empty": false
},
{
"param": "hover",
"value": 1,
"empty": false
}
],
"value": 0.1
}
}
},
{
"mark": {
"type": "text",
"align": "left",
"angle": -90,
"fontSize": 10
},
"encoding": {
"x": {
"timeUnit": "utcyearmonthdatehoursminutes",
"field": "TIMESTAMP",
"type": "ordinal",
"axis": {
"title": null,
"labels": false
}
},
"text": {
"field": "Attribute_TopX"
},
"y": {
"value": -5
},
"color": {
"condition": [
{
"test": "datum['COLORATTRIBUTE']=='COLOR_ITEM1'",
"value": "green"
},
{
"test": "datum['COLORATTRIBUTE']=='COLOR_ITEM2'",
"value": "steelblue"
}
],
"value": "black"
}
}
},{
"mark": {
"type": "text",
"align": "right",
"angle": -90,
"fontSize": 10
},
"encoding": {
"x": {
"timeUnit": "utcyearmonthdatehoursminutes",
"field": "TIMESTAMP",
"type": "ordinal",
"axis": {
"title": null,
"labels": false
}
},
"text": {
"field": "Attribute_BottomX"
},
"y": {
"value": "height"
},
"color": {
"condition": [
{
"test": "datum['COLORATTRIBUTE']=='COLOR_ITEM1'",
"value": "green"
},
{
"test": "datum['COLORATTRIBUTE']=='COLOR_ITEM2'",
"value": "steelblue"
}
],
"value": "black"
}
}
},
{
"mark": "rule",
"encoding": {
"x": {
"field": "TIMESTAMP",
"type": "temporal"
},
"opacity": {
"condition": [
{
"param": "hover",
"value": 0.8,
"empty": false
}
],
"value": 0
},
"size": {
"value": 1
},
"params": [
{
"name": "hover",
"select": {
"type": "point",
"encodings": [
"x"
],
"nearest": true,
"on": "mouseover"
}
},
{
"name": "legendhighlight",
"select": {
"type": "point",
"fields": [
"measure1"
]
},
"bind": "legend"
}
]
}
]
},
{
"layer": [
{
"transform": [
{
"fold": [
"ATTRIBUTE1",
"ATTRIBUTE2"
],
"as": [
"measure1",
"temp1"
]
}
],
"mark": {
"type": "boxplot"
},
"height": 150,
"width": 100,
"encoding": {
"x": {
"field": "measure1",
"type": "nominal",
"axis": {
"labels": false,
"ticks": false,
"title": null
}
},
"y": {
"field": "temp1",
"type": "quantitative",
"axis": {
"labels": false,
"ticks": false,
"title": null
},
"scale": {
"zero": false
}
},
"color": {
"field": "measure1",
"type": "nominal",
"legend": null
}
}
}
]
}
]
}
],
"resolve": {
"scale": {
"y": "independent",
"x": "shared",
"color": "independent"
}
}
}
And here is the params code that I try to add using Vega-Lite v5:
"params": [
{
"name": "grid",
"select": "interval",
"bind": "scales"
}
],
Thank you for your help!