Vega-lite Multiple aggregations in Transforms - vega

I want to implement two diff aggregations in a transform as they have different groupby conditions, but it seems not possible with vega-lite
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"data": {
{"response":200,"request":"/ST"},
{"response":500,"request":"/ST"},
{"response":200,"request":"/PP"},
{"response":500,"request":"/PP"},
{"response":200,"request":"/CP"},
{"response":200,"request":"/CP"},
{"response":500,"request":"/CP"},
{"response":500,"request":"/CP"},
{"response":500,"request":"/CP"},
{"response":500,"request":"/CP"},
{"response":500,"request":"/CP"},
{"response":500,"request":"/CP"},
{"response":503,"request":"/CP"},
{"response":503,"request":"/CP"},
{"response":503,"request":"/CP"}
"transform": [
{
"aggregate": [{
"op": "count",
"as": "response_count"
}],
"groupby": ["response","request"]
},
{
"aggregate": [{
"op": "count",
"as": "response_c"
}],
"groupby": ["request"]
}
],
{"mark": "bar",
"encoding": {
"x": {"field": "response_count", "type": "quantitative", "stack": "zero"},
"y": {"field": "request", "type": "nominal"},
"color": {"field": "response", "type": "nominal"}}
}
Is there any way of achieving this ? Are multiple aggregations like this supported?

Yes, multiple aggregations like this are supported, but your chart has undefined fields in the end because you have have not referenced them in your aggregations. You start with this data:
[
{"response": 200, "request": "/ST"},
{"response": 500, "request": "/ST"},
{"response": 200, "request": "/PP"},
{"response": 500, "request": "/PP"},
{"response": 200, "request": "/CP"},
{"response": 200, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 503, "request": "/CP"},
{"response": 503, "request": "/CP"},
{"response": 503, "request": "/CP"}
]
The first aggregation groups by "response" and "request", and adds "response_count" in each group, which looks like this:
[
{"response": 200, "request": "/ST", "response_count": 1},
{"response": 500, "request": "/ST", "response_count": 1},
{"response": 200, "request": "/PP", "response_count": 1},
{"response": 500, "request": "/PP", "response_count": 1},
{"response": 200, "request": "/CP", "response_count": 2},
{"response": 500, "request": "/CP", "response_count": 6},
{"response": 503, "request": "/CP", "response_count": 3},
]
Your second aggregation takes this, groups by "request", and adds "response_c" in each group, which looks like this:
[
{"request": "/ST", "response_c": 2},
{"request": "/PP", "response_c": 2},
{"request": "/CP", "response_c": 3},
]
Notice that any fields you don't reference in the aggregation are dropped.
Your specification then refers to fields that no longer exist in the dataset, which results in a blank chart.
You could fix this by specifying in the second aggregation what you want to happen with the fields that are dropped; for example, you could keep the sum of "response_count" and the minimum of "response" (open in editor):
{
"data": {
"values": [
{"response": 200, "request": "/ST"},
{"response": 500, "request": "/ST"},
{"response": 200, "request": "/PP"},
{"response": 500, "request": "/PP"},
{"response": 200, "request": "/CP"},
{"response": 200, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 503, "request": "/CP"},
{"response": 503, "request": "/CP"},
{"response": 503, "request": "/CP"}
]
},
"transform": [
{
"aggregate": [{"op": "count", "as": "response_count"}],
"groupby": ["response", "request"]
},
{
"aggregate": [
{"op": "count", "as": "response_c"},
{"op": "sum", "field": "response_count", "as": "response_count"},
{"op": "min", "field": "response", "as": "response"}
],
"groupby": ["request"]
}
],
"mark": "bar",
"encoding": {
"x": {"field": "response_count", "type": "quantitative", "stack": "zero"},
"y": {"field": "request", "type": "nominal"},
"color": {"field": "response", "type": "nominal"}
}
}
Better in this particular case might be to leave out the second aggregation altogether, in which case the second aggregation essentially happens visually via stacking of the bars (editor):
{
"data": {
"values": [
{"response": 200, "request": "/ST"},
{"response": 500, "request": "/ST"},
{"response": 200, "request": "/PP"},
{"response": 500, "request": "/PP"},
{"response": 200, "request": "/CP"},
{"response": 200, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 500, "request": "/CP"},
{"response": 503, "request": "/CP"},
{"response": 503, "request": "/CP"},
{"response": 503, "request": "/CP"}
]
},
"transform": [
{
"aggregate": [{"op": "count", "as": "response_count"}],
"groupby": ["response", "request"]
}
],
"mark": "bar",
"encoding": {
"x": {"field": "response_count", "type": "quantitative", "stack": "zero"},
"y": {"field": "request", "type": "nominal"},
"color": {"field": "response", "type": "nominal"}
}
}

Related

Modifying the Width of a Symbol Mark in Vega

I want to label the symbols in my Vega graph. Some of the labels are long, extending beyond the boundaries of my symbols. How do I extend the width of a symbol to handle long labels?
Update: Is there a way of increasing the width of a symbol mark?
This is a link to my code.
N.B: I tried using rect marks, whose widths are easier to modify. But the aesthetics of the rect mark do not work for my use case. My use case is a Force Transform force-directed graph.
Here is a working example using your Vega spec with Force transform and text box using reactive geometry as suggested by David.
View in Vega online editor
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A node-link diagram with force-directed layout, depicting character co-occurrence in the novel Les Misérables.",
"width": 500,
"height": 200,
"autosize": "pad",
"signals": [
{
"name": "nodeRadius",
"value": 50,
"bind": {"input": "range", "min": 1, "max": 100, "step": 1}
},
{
"name": "nodeCharge",
"value": -100,
"bind": {"input": "range", "min": -100, "max": 10, "step": 1}
},
{
"name": "linkDistance",
"value": 66,
"bind": {"input": "range", "min": 5, "max": 100, "step": 1}
},
{
"name": "textPadding",
"value": 5,
"bind": {"input": "range", "min": 0, "max": 20, "step": 1}
},
{
"name": "cornerRadius",
"value": 10,
"bind": {"input": "range", "min": 0, "max": 20, "step": 1}
},
{ "name": "showSymbol", "value": false, "bind": {"input": "checkbox"} },
],
"data": [
{
"name": "node_data",
"values": [
{"name": "A Name", "type": "node", "1d": 0},
{"name": "A Very Long Name", "type": "node", "1d": 1}
]
},
{"name": "edge_data", "values": [{"source": 0, "target": 1}]}
],
"marks": [
{
"type": "symbol",
"name": "nodes",
"from": {"data": "node_data"},
"encode": {
"update": {
"fill": {"value": "grey"},
"opacity": {"signal": "showSymbol ? 0.5 : 0"},
"size": {"signal": "PI * nodeRadius * nodeRadius"},
"shape": {"value": "circle"}
}
},
"transform": [
{
"type": "force",
"iterations": 300,
"static": {"signal": "false"},
"signal": "force",
"forces": [
{
"force": "center",
"x": {"signal": "width/2"},
"y": {"signal": "height/2"}
},
{"force": "collide", "radius": {"signal": "nodeRadius"}},
{"force": "nbody", "strength": {"signal": "nodeCharge * 10"}},
{
"force": "link",
"links": "edge_data",
"distance": {"signal": "linkDistance"}
}
]
}
]
},
{
"type": "path",
"from": {"data": "edge_data"},
"interactive": false,
"encode": {
"update": {"stroke": {"value": "#ccc"}, "strokeWidth": {"value": 0.5}}
},
"transform": [
{
"type": "linkpath",
"require": {"signal": "force"},
"shape": "line",
"sourceX": "datum.source.x",
"sourceY": "datum.source.y",
"targetX": "datum.target.x",
"targetY": "datum.target.y"
}
]
},
{
"type": "text",
"name": "textmark",
"from": {"data": "nodes"},
"interactive": false,
"encode": {
"enter": {"fill": {"value": "black"}, "fontSize": {"value": 16}},
"update": {
"y": {"field": "y", "offset": {"signal": "nodeRadius * -0.1"}},
"x": {"field": "x"},
"text": {"field": "datum.name"},
"align": {"value": "center"},
"baseline": {"value": "middle"}
}
},
"zindex": 1
},
{
"name": "rectmark",
"type": "rect",
"from": {"data": "textmark"},
"encode": {
"update": {
"x": {"field": "bounds.x1", "round": true, "offset": {"signal": "-textPadding"}},
"x2": {"field": "bounds.x2", "round": true, "offset": {"signal": "textPadding"}},
"y": {"field": "bounds.y1", "round": true, "offset": {"signal": "-textPadding"}},
"y2": {"field": "bounds.y2", "round": true, "offset": {"signal": "textPadding"}},
"cornerRadius": {"signal": "cornerRadius"},
"fill": {"value": "aliceblue"},
"stroke": {"value": "steelblue"}
}
}
}
]
}
It isn't clear what you're asking. Do you mean just increase the size of the symbol statically like this?
If so, just put a value in the size property.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A node-link diagram with force-directed layout, depicting character co-occurrence in the novel Les Misérables.",
"width": 700,
"height": 500,
"autosize": "pad",
"signals": [
{
"name": "nodeRadius",
"value": 50,
"bind": {"input": "range", "min": 1, "max": 50, "step": 1}
},
{
"name": "nodeCharge",
"value": -100,
"bind": {"input": "range", "min": -100, "max": 10, "step": 1}
},
{
"name": "linkDistance",
"value": 66,
"bind": {"input": "range", "min": 5, "max": 100, "step": 1}
}
],
"data": [
{
"name": "node_data",
"values": [
{"name": "A Name", "type": "node", "1d": 0},
{"name": "A Very Long Name", "type": "node", "1d": 1}
]
},
{"name": "edge_data", "values": [{"source": 0, "target": 1}]}
],
"marks": [
{
"type": "symbol",
"name": "nodes",
"from": {"data": "node_data"},
"encode": {
"enter": {
"fill": {"value": "steelblue"},
"size": {"value": 10000},
"tooltip": {"field": "name"}
}
},
"transform": [
{
"type": "force",
"iterations": 300,
"static": {"signal": "false"},
"signal": "force",
"forces": [
{
"force": "center",
"x": {"signal": "width/2"},
"y": {"signal": "height/2"}
},
{"force": "collide", "radius": {"signal": "nodeRadius"}},
{"force": "nbody", "strength": {"signal": "nodeCharge * 10"}},
{
"force": "link",
"links": "edge_data",
"distance": {"signal": "linkDistance"}
}
]
}
]
},
{
"type": "path",
"from": {"data": "edge_data"},
"interactive": false,
"encode": {
"update": {"stroke": {"value": "#ccc"}, "strokeWidth": {"value": 0.5}}
},
"transform": [
{
"type": "linkpath",
"require": {"signal": "force"},
"shape": "line",
"sourceX": "datum.source.x",
"sourceY": "datum.source.y",
"targetX": "datum.target.x",
"targetY": "datum.target.y"
}
]
},
{
"type": "text",
"from": {"data": "nodes"},
"interactive": false,
"enter": {"fill": {"value": "black"}, "fontSize": {"value": 10}},
"encode": {
"update": {
"y": {"field": "y", "offset": {"signal": "nodeRadius * -0.1"}},
"x": {"field": "x"},
"text": {"field": "datum.name"},
"align": {"value": "center"}
}
}
}
]
}
Or you can split the word like this.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A node-link diagram with force-directed layout, depicting character co-occurrence in the novel Les Misérables.",
"width": 700,
"height": 500,
"autosize": "pad",
"signals": [
{
"name": "nodeRadius",
"value": 50,
"bind": {"input": "range", "min": 1, "max": 50, "step": 1}
},
{
"name": "nodeCharge",
"value": -100,
"bind": {"input": "range", "min": -100, "max": 10, "step": 1}
},
{
"name": "linkDistance",
"value": 66,
"bind": {"input": "range", "min": 5, "max": 100, "step": 1}
}
],
"data": [
{
"name": "node_data",
"values": [
{"name": "A Name", "type": "node", "1d": 0},
{"name": ["A Very", "Long Name"], "type": "node", "1d": 1}
]
},
{"name": "edge_data", "values": [{"source": 0, "target": 1}]}
],
"marks": [
{
"type": "symbol",
"name": "nodes",
"from": {"data": "node_data"},
"encode": {
"enter": {
"fill": {"value": "steelblue"},
"size": {"value": 10000},
"tooltip": {"field": "name"}
}
},
"transform": [
{
"type": "force",
"iterations": 300,
"static": {"signal": "false"},
"signal": "force",
"forces": [
{
"force": "center",
"x": {"signal": "width/2"},
"y": {"signal": "height/2"}
},
{"force": "collide", "radius": {"signal": "nodeRadius"}},
{"force": "nbody", "strength": {"signal": "nodeCharge * 10"}},
{
"force": "link",
"links": "edge_data",
"distance": {"signal": "linkDistance"}
}
]
}
]
},
{
"type": "path",
"from": {"data": "edge_data"},
"interactive": false,
"encode": {
"update": {"stroke": {"value": "#ccc"}, "strokeWidth": {"value": 0.5}}
},
"transform": [
{
"type": "linkpath",
"require": {"signal": "force"},
"shape": "line",
"sourceX": "datum.source.x",
"sourceY": "datum.source.y",
"targetX": "datum.target.x",
"targetY": "datum.target.y"
}
]
},
{
"type": "text",
"from": {"data": "nodes"},
"interactive": false,
"enter": {"fill": {"value": "black"}, "fontSize": {"value": 10}},
"encode": {
"update": {
"y": {"field": "y", "offset": {"signal": "nodeRadius * -0.1"}},
"x": {"field": "x"},
"text": {"field": "datum.name"},
"align": {"value": "center"}
}
}
}
]
}
If you want something dynamic to size the node to the label extent, you have to use reactive geometry.
Using reactive geometry for you. This example is from jheer on GitHub.
This sets the rectangles width and height according to the text mark.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 100,
"height": 100,
"data": [
{"name": "labels", "values": [{"label": "Text"}]}
],
"marks": [
{
"type": "group",
"signals": [
{"name": "bgoffset", "value": 3}
],
"marks": [
{
"name": "textmark",
"type": "text",
"from": {"data": "labels"},
"encode": {
"enter": {
"text": {"field": "label"},
"x": {"value": 50},
"y": {"value": 50},
"fontSize": {"value": 14},
"align": {"value": "center"},
"baseline": {"value": "middle"}
}
},
"zindex": 1
},
{
"name": "rectmark",
"type": "rect",
"from": {"data": "textmark"},
"encode": {
"enter": {
"x": {"field": "bounds.x1", "round": true, "offset": {"signal": "-bgoffset"}},
"x2": {"field": "bounds.x2", "round": true, "offset": {"signal": "bgoffset"}},
"y": {"field": "bounds.y1", "round": true, "offset": {"signal": "-bgoffset"}},
"y2": {"field": "bounds.y2", "round": true, "offset": {"signal": "bgoffset"}},
"fill": {"value": "aliceblue"},
"stroke": {"value": "steelblue"}
}
}
}
]
}
]
}

How to display multiple charts with varying x-scales side by side in Vega

I have a set of charts with the same y-scale but varying x-scales. I am using hconcat to display them side by side. In order to conserve space and avoid repetition, I have disabled the y-axis for all but the first chart. However, this is causing the title of the first chart to offset:
This is a link to a Vega Editor.
As the blue circle indicates, the two titles, "Chain" and "Mini Invaders," are not in line. Is there a way to fix this?
I have tried to express these charts using facet but as far as I can tell, facets do not permit varying x-scales. However, please do let me know if this is somehow possible with facets.
You need labelBound: true in your spec.
Editor
{
"config": {
"view": {
"continuousWidth": 400,
"continuousHeight": 300,
"stroke": "#000000",
"strokeOpacity": 1,
"strokeWidth": 2
},
"axis": {"labelFontSize": 24, "titleFontSize": 24, "labelBound":true},
"legend": {"labelFontSize": 24, "labelLimit": 0, "titleFontSize": 32},
"title": {"baseline": "bottom", "fontSize": 24}
},
"hconcat": [
{
"layer": [
{
"mark": {"type": "area", "clip": true, "opacity": 0.2},
"encoding": {
"color": {
"field": "Variations",
"legend": {
"orient": "top",
"symbolOpacity": 1,
"symbolSize": 200,
"symbolStrokeWidth": 3,
"symbolType": "stroke"
},
"scale": {
"domain": ["Original Algorithm"],
"range": [
"#e41a1c",
"#377eb8",
"#4daf4a",
"#984ea3",
"#a65628",
"#646464"
]
},
"type": "nominal"
},
"x": {"field": "step", "type": "quantitative"},
"y": {
"axis": {"labels": true, "tickCount": 5, "title": null},
"field": "lower",
"type": "quantitative"
},
"y2": {"field": "upper"}
}
},
{
"mark": {"type": "line", "clip": true},
"encoding": {
"color": {"field": "Variations", "type": "nominal"},
"x": {"field": "step", "type": "quantitative"},
"y": {
"field": "regret",
"scale": {"domain": [0, 1]},
"type": "quantitative"
}
}
}
],
"height": 200,
"title": "Chain",
"transform": [{"filter": "(datum.domain === 'Chain')"}],
"width": 200
},
{
"layer": [
{
"mark": {"type": "area", "clip": true, "opacity": 0.2},
"encoding": {
"color": {
"field": "Variations",
"legend": {
"orient": "top",
"symbolOpacity": 1,
"symbolSize": 200,
"symbolStrokeWidth": 3,
"symbolType": "stroke"
},
"scale": {
"domain": ["Original Algorithm"],
"range": [
"#e41a1c",
"#377eb8",
"#4daf4a",
"#984ea3",
"#a65628",
"#646464"
]
},
"type": "nominal"
},
"x": {"field": "step", "type": "quantitative"},
"y": {
"axis": {"labels": false, "tickCount": 5, "title": null},
"field": "lower",
"type": "quantitative"
},
"y2": {"field": "upper"}
}
},
{
"mark": {"type": "line", "clip": true},
"encoding": {
"color": {"field": "Variations", "type": "nominal"},
"x": {"field": "step", "type": "quantitative"},
"y": {
"field": "regret",
"scale": {"domain": [0, 1]},
"type": "quantitative"
}
}
}
],
"height": 200,
"title": "Mini Invaders",
"transform": [{"filter": "(datum.domain === 'Mini Invaders')"}],
"width": 200
}

Stacked barchart in Vega

I am trying to make a stacked barchart in Vega and have hit a wall where I swear that my code should work, based on the several examples I've been cross referencing, but instead I keep getting perfect axes...with no bars.
The way it's supposed to work in this example is that Alamo's "Operations" "Debt" and "Below Cap" should stack, with State Average having the same categories of data stacked in the same order next to it. Both should sum to the same level (1). The transformed data looks to be in good shape, as the y0/y1 and order are correct.
I initially assumed the problem is in the marks section since that's where the bars are defined but I can't identify what the issue is there, so now I'm wondering if it's something else. But I don't know what else to try.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A stacked bar chart describing ad valorem taxes in Texas community college districts.",
"width": 300,
"height": 300,
"padding": 5,
"background": "white",
"style": "cell",
"data": [
{
"name": "source_0",
"values": [
{
"name": "Operations (MO)",
"amount": 0.1078,
"district": "Alamo",
"sort": 1,
"y0": 0,
"y1": 0.1078
},
{
"name": "Debt (IS)",
"amount": 0.0414,
"district": "Alamo",
"sort": 2,
"y0": 0.1078,
"y1": 0.1492
},
{
"name": "Below Cap",
"amount": 0.8508,
"district": "Alamo",
"sort": 3,
"y0": 0.1492,
"y1": 1
},
{
"name": "Operations (MO)",
"amount": 0.152,
"district": "State Average",
"sort": 1,
"y0": 0,
"y1": 0.152
},
{
"name": "Debt (IS)",
"amount": 0.027,
"district": "State Average",
"sort": 2,
"y0": 0.152,
"y1": 0.179
},
{
"name": "Below Cap",
"amount": 0.821,
"district": "State Average",
"sort": 3,
"y0": 0.179,
"y1": 1
}
],
"format": {"type": "json"},
"transform": [
{
"type": "stack",
"groupby": ["district"],
"sort": {"field": "sort"},
"field": "amount"
}
]
}
],
"scales": [
{
"name": "x",
"type": "band",
"range": "width",
"domain": {"data": "source_0", "field": "district"}
},
{
"name": "y",
"type": "linear",
"range": "height",
"nice": true,
"zero": true,
"domain": {"data": "source_0", "field": "y1"}
},
{
"name": "color",
"type": "ordinal",
"range": "category",
"domain": {"data": "source_0", "field": "name"}
}
],
"axes": [
{"orient": "bottom", "scale": "x", "zindex": 1},
{"orient": "left", "scale": "y", "zindex": 1}
],
"marks": [
{
"type": "rect",
"from": {"data": "source_0"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "district"},
"width": {"scale": "x", "band": 1},
"y": {"scale": "y", "field": "y1"},
"y2": {"scale": "y", "value": "y0"},
"fill": {"scale": "color", "field": "name"}
}
}
}
]
}
Change your y2 from value to field. Editor
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A stacked bar chart describing ad valorem taxes in Texas community college districts.",
"width": 300,
"height": 300,
"padding": 5,
"background": "white",
"style": "cell",
"data": [
{
"name": "source_0",
"values": [
{
"name": "Operations (MO)",
"amount": 0.1078,
"district": "Alamo",
"sort": 1,
"y0": 0,
"y1": 0.1078
},
{
"name": "Debt (IS)",
"amount": 0.0414,
"district": "Alamo",
"sort": 2,
"y0": 0.1078,
"y1": 0.1492
},
{
"name": "Below Cap",
"amount": 0.8508,
"district": "Alamo",
"sort": 3,
"y0": 0.1492,
"y1": 1
},
{
"name": "Operations (MO)",
"amount": 0.152,
"district": "State Average",
"sort": 1,
"y0": 0,
"y1": 0.152
},
{
"name": "Debt (IS)",
"amount": 0.027,
"district": "State Average",
"sort": 2,
"y0": 0.152,
"y1": 0.179
},
{
"name": "Below Cap",
"amount": 0.821,
"district": "State Average",
"sort": 3,
"y0": 0.179,
"y1": 1
}
],
"format": {"type": "json"},
"transform": [
{
"type": "stack",
"groupby": ["district"],
"sort": {"field": "sort"},
"field": "amount"
}
]
}
],
"scales": [
{
"name": "x",
"type": "band",
"range": "width",
"domain": {"data": "source_0", "field": "district"}
},
{
"name": "y",
"type": "linear",
"range": "height",
"nice": true,
"zero": true,
"domain": {"data": "source_0", "field": "y1"}
},
{
"name": "color",
"type": "ordinal",
"range": "category",
"domain": {"data": "source_0", "field": "name"}
}
],
"axes": [
{"orient": "bottom", "scale": "x", "zindex": 1},
{"orient": "left", "scale": "y", "zindex": 1}
],
"marks": [
{
"type": "rect",
"from": {"data": "source_0"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "district"},
"width": {"scale": "x", "band": 1},
"y": {"scale": "y", "field": "y1"},
"y2": {"scale": "y", "field": "y0"},
"fill": {"scale": "color", "field": "name"}
}
}
}
]
}

Vega-Lite: How to use slider value in transform calculation

How do I use the value of a slider in the transform?
This example from vega online editor plots a sine and cosine wave.
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Plots two functions using a generated sequence.",
"width": 300,
"height": 150,
"data": {
"sequence": {
"start": 0,
"stop": 12.7,
"step": 0.1,
"as": "x"
}
},
"transform": [
{
"calculate": "sin(datum.x)",
"as": "sin(x)"
},
{
"calculate": "cos(datum.x)",
"as": "cos(x)"
},
{
"fold": ["sin(x)", "cos(x)"]
}
],
"mark": "line",
"encoding": {
"x": {
"type": "quantitative",
"field": "x"
},
"y": {
"field": "value",
"type": "quantitative"
},
"color": {
"field": "key",
"type": "nominal",
"title": null
}
}
}
I would like to add two sliders and use their values in the calculation. I can define sliders using:
"selection" : {
"amp" : {
"type" : "single",
"fields" : ["sin", "cos"],
"bind": {
"sin": { "input" : "range", "min": 0.0, "max": 10.0, "step": 0.1},
"cos": { "input" : "range", "min": 0.0, "max": 10.0, "step": 0.1}
}
}
},
How do I access the slider values to use in the calculations? Something like
{
"calculate": "amp.sin * sin(datum.x)",
"as": "sin(x)"
},
You can do this in exactly the way you wrote in your question. Additionally, adding an initial value will make the selections valid before you interact with them.
Here is a full example (vega editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "Plots two functions using a generated sequence.",
"width": 300,
"height": 150,
"data": {"sequence": {"start": 0, "stop": 12.7, "step": 0.1, "as": "x"}},
"transform": [
{"calculate": "amp.sin * sin(datum.x)", "as": "sin(x)"},
{"calculate": "amp.cos * cos(datum.x)", "as": "cos(x)"},
{"fold": ["sin(x)", "cos(x)"]}
],
"mark": "line",
"encoding": {
"x": {"type": "quantitative", "field": "x"},
"y": {"field": "value", "type": "quantitative"},
"color": {"field": "key", "type": "nominal", "title": null}
},
"selection": {
"amp": {
"type": "single",
"fields": ["sin", "cos"],
"init": {"sin": 1, "cos": 1},
"bind": {
"sin": {"input": "range", "min": 0, "max": 10, "step": 0.1},
"cos": {"input": "range", "min": 0, "max": 10, "step": 0.1}
}
}
}
}

Why I can't add legend to my chart in vega?

this is my vega code, and I do write code to add legend to my pie chart, but it can't work. Could you please help me?
{
"$schema": "https://vega.github.io/schema/vega/v4.json",
"width": 300,
"height": 300,
"autosize": "none", //put in my data
"signals": [
{
"name": "startAngle",
"value": 0,
"bind": {"input": "range", "min": 0, "max": 6.29, "step": 0.01}
},
{
"name": "endAngle",
"value": 6.29,
"bind": {"input": "range", "min": 0, "max": 6.29, "step": 0.01}
},
{
"name": "padAngle",
"value": 0,
"bind": {"input": "range", "min": 0, "max": 0.1}
},
{
"name": "innerRadius",
"value": 0,
"bind": {"input": "range", "min": 0, "max": 90, "step": 1}
},
{
"name": "cornerRadius",
"value": 0,
"bind": {"input": "range", "min": 0, "max": 10, "step": 0.5}
},
{"name": "sort", "value": false, "bind": {"input": "checkbox"}}
], //set the control bar
"data": [
{
"name": "table",
"values": [
{"id": "BenCarsonNumber", "field": 564553},
{"id": "BernieSanders", "field": 11958297},
{"id": "CarlyFiorina", "field": 15191},
{"id": "ChrisChristie", "field": 24353},
{"id": "DonaldTrump", "field": 13301237},
{"id": "HillaryClinton", "field": 15691617},
{"id": "JebBush", "field": 94411},
{"id": "JohnKasich", "field": 4159528},
{"id": "MarcoRubio", "field": 3320810},
{"id": "Malley", "field": 752},
{"id": "MikeHuckabee", "field": 3345},
{"id": "NoPreference", "field": 8152},
{"id": "RandPaul", "field": 8479},
{"id": "RickSantorum", "field": 1782},
{"id": "TedCruz", "field": 7602299},
{"id": "Uncommitted", "field": 43} //this is my data
],
"transform": [ //try to make a pie chart
{
"type": "pie",
"field": "field",
"startAngle": {"signal": "startAngle"},
"endAngle": {"signal": "endAngle"},
"sort": {"signal": "sort"}
}
]
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {"data": "table", "field": "id"},
"range": {"scheme": "category20"}
}
],
"legends": [ //there is my legend code
{
"stroke": "color",
"title": "Origin",
"encode": {
"symbols": {
"update": {
"fill": {"value": ""},
"strokeWidth": {"value": 2},
"size": {"value": 64}
}
}
}
}
],
"marks": [
{
"type": "arc",
"from": {"data": "table"},
"encode": {
"enter": {
"fill": {"scale": "color", "field": "id"},
"x": {"signal": "width / 2"},
"y": {"signal": "height / 2"}
},
"update": {
"startAngle": {"field": "startAngle"},
"endAngle": {"field": "endAngle"},
"padAngle": {"signal": "padAngle"},
"innerRadius": {"signal": "innerRadius"},
"outerRadius": {"signal": "width / 2"},
"cornerRadius": {"signal": "cornerRadius"}
}
}
}
]
}
everything works fine, expect there is no legend for the chart.
or If there is a better way to write a pie chart like this? but I can't come out with anything new. Please help me!
Thank you so much for helping!
You would need to update your legends section with "orient": "top-right".
Here's vega editor full spec
...
"legends": [
{ ....
"orient": "top-right",
....
}
],
...