I'm trying to add a text mark to the nodes in the force-directed-layout example on the github page of vega.
I converted the symbol mark to a group mark and moved the "encode" part to a child "symbol" mark. In this new group-mark I now also add a text mark which I give the name of the node.
This is the nodes mark, the "on" and "transform" parts are left out because these are unchanged.
{
"name": "nodes",
"type": "group",
"zindex": 1,
"from": {
"data": "node-data"
},
"marks": [
{
"type": "symbol",
"encode": {
"enter": {
"fill": {
"scale": "color",
"field": "group"
},
"stroke": {
"value": "white"
}
},
"update": {
"size": {
"signal": "2 * nodeRadius * nodeRadius"
},
"cursor": {
"value": "pointer"
}
}
}
},
{
"type": "text",
"interactive": false,
"encode": {
"enter": {
"fill": {
"value": "black"
},
"fontSize": {
"value": 12
},
"align": {
"value": "center"
},
"text": {
"field": "name"
},
"y": {
"value": -5
}
}
}
}
],
"on": [...],
"transform": [...]
}
Expected was to see the name of the node above each node, but the text AND the symbol become invisible.
Steps to Reproduce
Make the type "group", add a "marks" array, add a mark object with type "symbol" to this marks array
-> the nodes still show
Move the encode part to the nested symbol group
-> the nodes dissapear
Adding the text mark also does nothing
I have a hunch that its the "field" property that borks when you try to nest it while keeping the data in the parent because the text mark does show in the group when I give it a fixed value, but I can't seem to figured out how to get it working.
(I thought this was the way because the docs say that a child mark gets the parent data automatically when ommiting a data field)
Within a group, you have to use {"parent": <field_name>} to refer to a field. For example, to refer to the field "group" in the parent use:
"field": {"parent": "group"}}
See an example here.
Adding the following mark also works, without breaking dragging (example link):
{
"type": "text",
"from": {"data": "nodes"},
"interactive": false,
"enter": {
"fill": {"value": "black"},
"fontSize": {"value": 10}
},
"encode": {
"update": {
"y": {"field": "y", "offset": {"signal": "nodeRadius * -0.9"}},
"x": {"field": "x"},
"text": {"field": "datum.name"},
"align": {"value": "center"}
}
}
}
This text mark uses the symbol mark (called nodes) as its backing data source. See https://vega.github.io/vega/docs/marks/#reactive-geometry.
Related
To get to know how events work in VEGA, I gave myself the simple exercice to render a dot and a text positioned on the cursors coordinates in a given view.
I managed to make a symbol follow the mouse coordinates, yet when I try to make two types of marks ( text and symbol) follow the mouse , it doesn't render them both but the first one appearing in the marks [ ] array.
Any ideas ?
Following specification is used in the exercice :
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 600,
"height": 600,
"signals": [
{
"name": "position",
"on": [
{
"events": {
"type": "mousemove"
},
"update": "xy()"
}
]
},
{
"name": "positionDot",
"on": [
{
"events": {
"type": "mousemove"
},
"update": "xy()"
}
]
}
],
"marks": [
{
"type": "text",
"encode": {
"enter": {
"fill": {
"value": "#000"
},
"text": {
"value": "Text Label"
}
},
"update": {
"opacity": {
"value": 1
},
"x": {
"signal": "position[0]+20"
},
"y": {
"signal": "position[1]+20"
},
"fontSize": {
"value": 50
}
}
}
},
{
"name": "dot",
"type": "symbol",
"encode": {
"enter": {
"fill": {
"value": "#939597"
},
"stroke": {
"value": "#652c90"
},
"x": {
"value": 0
},
"y": {
"value": 0
}
},
"update": {
"x": {
"signal": "positionDot[0]"
},
"y": {
"signal": "position[1]"
},
"size": {
"value": 550
},
"opacity": {
"value": 1
}
},
"hover": {
"opacity": {
"value": 0.5
}
}
}
}
]
}
https://vega.github.io/editor/#/gist/1dcd1034a1d8139b3de49f041ed1ed4b/spec.json
Your example works as expected if an initial value (using "init" or "value") is included in signal position:
"signals": [
{
"name": "position",
"init": [0, 0],
"on": [
{
"events": {
"type": "mousemove"
},
"update": "xy()"
}
]
},
View in Vega online editor
I'm trying to format values as currency in the Vega-Lite editor. I'm attempting to copy the docs but I'm getting a weird error. The Y axis is a numerical value. Passing in a formatting string gives "value expected".
Here's the json:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Protocol Chart",
"width": 500,
"height": 225,
"data": {
"values": [
{
"asset": "eth",
"time": "2021-06-15T00:00:00Z",
"ReferenceRateUSD": "2577.04473863238"
},
{
"asset": "eth",
"time": "2021-06-16T00:00:00Z",
"ReferenceRateUSD": "2552.74103641146"
},
{
"asset": "eth",
"time": "2021-06-17T00:00:00Z",
"ReferenceRateUSD": "2360.99938690824"
}
]
},
"config": {
"view": {
"stroke": "transparent"
}
},
"mark": "line",
"encoding": {
"x": {
"axis": {
"domainColor": "#DDD",
"grid": false,
"labelColor": "#AEAEAE",
"ticks": false,
"labelPadding": 10
},
"field": "time",
"type": "temporal",
"title": ""
},
"y": {
"axis": {
"labelOffset": 2,
"domainColor": "white",
"labelColor": "#AEAEAE",
"ticks": false,
"labelPadding": 10,
"format": '$.2f'
},
"field": "ReferenceRateUSD",
"type": "quantitative",
"title": "",
"scale": {
"zero": false
}
},
"color": {
"field": "doesntmatter",
"type": "nominal",
"legend": null,
"scale": {
"range": ["#91DB97"]
}
}
}
}
What am I missing here? How do I get it to accept my formatting string?
"$.2f" looks like a the correct d3-format string for currency, but note that this is only valid if the associated formatType is "number" (see axis label docs).
Since you did not include a full reproducible example of the problem you're seeing, I can only venture a guess that your data type is not numeric, and this is why the formatting is failing. If that's not the case, I'd suggest editing your question to provide a complete example of the error you're seeing.
Edit: your full example appears to work correctly with the current version of vega/vega-lite (view in editor):
Perhaps you need to update your vega/vega-lite libraries?
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:
It's possible to specify Rule as encoding over the data. But sometimes it's too verbose. Is there a shorter way to specify it with just a single number?
In example below I want to draw a horizontal line with y=1 and it requires me to specify a calculate transform. Wonder if it's possible with something more compact, like:
"layer": [
...,
{ "mark": { "type": "rule", "y": 1 }, // Specify ruler with just a single line
...
]
Playground
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"transform":[
{ "calculate": "1", "as": "one" }
],
"layer": [
{
"mark": { "type": "bar" },
"encoding": {
"x": { "field": "diff", "type": "quantitative" },
"y": { "field": "diff", "type": "quantitative" }
}
},
{
"mark": { "type": "rule" },
"encoding": {
"y": { "field": "one", "type": "quantitative" }
}
}
],
"data": {
"values": [
{ "diff": 1 },
{ "diff": 2 },
{ "diff": 3 }
]
}
}
You can specify a single value using the "value" field in the encoding; e.g.
{
"mark": { "type": "rule" },
"encoding": {
"y": { "value": 133 }
}
}
(Playground)
But be aware this value is a value in the axis domain, rather than in the data domain; i.e. it represents pixels from the top-left of the chart.
If you want to specify a value in the data domain, there is no such shorthand. You have to either use a transform (as you did in your question) or define a new dataset for your layer. The most compact way of doing this, I think, is something like this:
{
"mark": { "type": "rule" },
"data": {"values": {"y": 1}},
"encoding": {
"y": { "field": "y" }
}
}
I use vega in Kibana.
I select two values from two different index in section "data". But now I need to summarize this values and visualize it in the section "marks". Is anybody know, how can I do this? Now in the section "marks" I use only one value from first "data".
My code is the following:
{
"$schema": "https://vega.github.io/schema/vega/v3.0.json",
"title": {
"text": "Lead time, hr.",
"orient": "bottom"
},
"data": [
{
"name": "source_1",
"url": {
"index": "metrics-bitbucket-*",
"%context_query%": "#timestamp",
"body": {
"size": 0,
"aggs": {
"etb": {
"avg": {
"field": "elapsed_time",
"script": {"source": "_value/3600*10"}
}
}
}
}
},
"format": {"type": "json", "property": "aggregations.etb"}
},
{
"name": "source_2",
"url": {
"index": "metrics-jenkins-*",
"%context_query%": "#timestamp",
"body": {
"size": 0,
"aggs": {
"etj": {
"avg": {
"field": "elapsed_time",
"script": {"source": "_value/3600*10"}
}
}
}
}
},
"format": {"type": "json", "property": "aggregations.etj"}
}
],
"marks": {
"type": "text",
"from": {"data": "source_1"},
"encode": {
"update": {
"text": {"signal": "round(datum.value)/10"},
"fontSize": {"value": 60},
"fontStyle": {"value": "bold"},
"x": {"signal": "width/2-50"},
"y": {"signal": "height/2"}
}
}
}
}
You essentially have two lists of data objects: source1: [{}, {}, ...] and source2: [{}, {}, {}, ...]. When you draw items, you have to specify just one data source. That data source could be the concatenation of the first two, e.g. you create source3 with its source parameter set to ["source1", "source2"], which includes all elements from both, but I suspect this is not what you want here. Rather, you need to merge the data using lookup transform - iterate over the items in one data source, and pull the corresponding values from another data source. Afterwards, add a formula transform to sum the values. The mark would than use the result of the formula for drawing.