Reputation: 2908
I want to make a chart that has "spikes" as markers. And to denote the "severity" or the "quantitative" nature of the data, I want to scale the "spikes" longer but NOT wider. Currently, when I use the size
encoding it increases the area of the "spike", which is undesirable. I used "aspect": false
too but the results did not change -
Vega-Lite Spec
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A simple bar chart with embedded data.",
"data": {
"values": [
{"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43},
{"a": "D", "b": 91}, {"a": "E", "b": 81}, {"a": "F", "b": 53},
{"a": "G", "b": 19}, {"a": "H", "b": 87}, {"a": "I", "b": 52}
]
},
"mark": {"type": "point", "shape":"M -1 0 L0 -10 L1 0", "fill": "red", "opacity": 0.5, "stroke": "black", "strokeOpacity": 1 },
"encoding": {
"x": {"field": "a", "type": "ordinal"},
"y": {"field": "b", "type": "quantitative"},
"size": {"field": "b", "type": "quantitative"}
}
}
Then I thought that maybe I can specify shape
as an encoding and provide custom SVG that only changes in height, as PATH value to the data itself and pass that in the shape encoding. But of course that didn't work. Vega-Lite assigned its own shapes -
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A simple bar chart with embedded data.",
"data": {
"values": [
{"a": "A", "b": 28, "c":"M -1 0 L0 -10 L1 0"}, {"a": "B", "b": 55, "c":"M -1 0 L0 -5 L1 0"}, {"a": "C", "b": 43, "c":"M -1 0 L0 -20 L1 0"},
{"a": "D", "b": 91, "c":"M -1 0 L0 -1 L1 0"}
]
},
"mark": {"type": "point", "fill": "red", "opacity": 0.5, "stroke": "black", "strokeOpacity": 1 },
"encoding": {
"x": {"field": "a", "type": "ordinal"},
"y": {"field": "b", "type": "quantitative"},
"shape": {"field": "c", "type": "quantitative"}
}
}
I also played around with url
encoding in point
mark as well as image
mark, but they did not yield anything.
I saw Path Mark in Vega, which may be useful but I do not see it in Vega-Lite. If it can somehow be used then that is fine too.
Any idea how do I make this happen?
Main idea is to have the width of the marker same, but scale the height. I don't mind doing it via encoding channels or arguments/parameters or specifying an SVG PATH for each data point, either way is fine.
After fiddling with vega, I got around to the following -
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A simple bar chart with embedded data.",
"background": "white",
"padding": 5,
"height": 700,
"style": "cell",
"data": [
{
"name": "source_0",
"values": [
{"a": "A", "b": 1.5, "c": 0},
{"a": "B", "b": 0.5, "c": 0},
{"a": "C", "b": 10, "c": 0},
{"a": "D", "b": 1, "c": 0}
]
},
{
"name": "data_0",
"source": "source_0",
"transform": [
{
"type": "filter",
"expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])"
}
]
}
],
"signals": [
{"name": "x_step", "value": 20},
{
"name": "width",
"update": "bandspace(domain('x').length, 1, 0.5) * x_step"
}
],
"marks": [
{
"name": "marks",
"type": "symbol",
"style": ["path"],
"from": {"data": "data_0"},
"encode": {
"update": {
"opacity": {"value": 0.7},
"fill": {"value": "red"},
"stroke": {"value": "red"},
"strokeOpacity": {"value": 1},
"strokeWidth": {"value": 0.25},
"shape": {"value": "M -1 0 L0 -10 L1 0 Z"},
"ariaRoleDescription": {"value": "point"},
"description": {
"signal": "\"a\" + \": \" + (isValid(datum[\"a\"]) ? datum[\"a\"] : \"\"+datum[\"a\"]) + \"; \" + \"b\" + \": \" + (format(datum[\"b\"], \"\"))"
},
"x": {"scale": "x", "field": "a"},
"y": {"scale": "y", "field": "c"},
"scaleY": {"field": "b", "type": "quantitative"}
}
}
}
],
"scales": [
{
"name": "x",
"type": "point",
"domain": {"data": "data_0", "field": "a", "sort": true},
"range": {"step": {"signal": "x_step"}},
"padding": 0.5
},
{
"name": "y",
"type": "linear",
"domain": {"data": "data_0", "field": "b"},
"range": [{"signal": "height"}, 0],
"nice": true,
"zero": true
},
{
"name": "size",
"type": "linear",
"domain": {"data": "data_0", "field": "b"},
"range": [0, 361],
"zero": true
}
],
"axes": [
{
"scale": "y",
"orient": "left",
"gridScale": "x",
"grid": true,
"tickCount": {"signal": "ceil(height/40)"},
"domain": false,
"labels": false,
"aria": false,
"maxExtent": 0,
"minExtent": 0,
"ticks": false,
"zindex": 0
},
{
"scale": "x",
"orient": "bottom",
"grid": false,
"title": "a",
"labelAlign": "right",
"labelAngle": 270,
"labelBaseline": "middle",
"labelOverlap": true,
"zindex": 0
},
{
"scale": "y",
"orient": "left",
"grid": false,
"title": "b",
"labelOverlap": true,
"tickCount": {"signal": "ceil(height/40)"},
"zindex": 0
}
]
}
I tried to convert this to Vega-Lite but it doesn't seem to work -
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A simple bar chart with embedded data.",
"data": {
"values": [
{"a": "A", "b": 2}, {"a": "B", "b": 5}, {"a": "C", "b": 4},
{"a": "D", "b": 9}
]
},
"mark": {"type": "point", "shape":"M -1 0 L0 -10 L1 0", "fill": "red", "opacity": 0.5, "stroke": "black", "strokeOpacity": 1 },
"encoding": {
"x": {"field": "a", "type": "ordinal", "axis": {"labelAngle": 0}},
"y": {"field": "b", "type": "quantitative"},
"scaleY": {"field": "b", "type": "quantitative"}
}
}
Error
Property scaleY is not allowed.
Upvotes: 2
Views: 638
Reputation: 86310
Your second approach, of providing the SVG path in the shape
encoding, will work if you set the scale
to null
(open in editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A simple bar chart with embedded data.",
"data": {
"values": [
{"a": "A", "b": 28, "c":"M -1 0 L0 -10 L1 0"},
{"a": "B", "b": 55, "c":"M -1 0 L0 -5 L1 0"},
{"a": "C", "b": 43, "c":"M -1 0 L0 -20 L1 0"},
{"a": "D", "b": 91, "c":"M -1 0 L0 -1 L1 0"}
]
},
"mark": {"type": "point", "fill": "red", "opacity": 0.5, "stroke": "black", "strokeOpacity": 1 },
"encoding": {
"x": {"field": "a", "type": "ordinal"},
"y": {"field": "b", "type": "quantitative"},
"shape": {"field": "c", "type": "quantitative", "scale": null}
}
}
Vega-Lite does not provide the equivalent of Vega's ScaleY
encoding, so if you want that approach you will have to work in Vega directly.
Upvotes: 3