How to get Vega/Vega-Lite gradient to behave correctly when zoomed in - gradient

I have created a graph with a gradient which is zoomable (see code below), but the gradient doesn't behave the way I'd like. When the user zooms in, the gradient effectively disappears. This effect is particularly pronounced if the data contains a big spike, and the user zooms into a different part of the data.
In my example, try changing the domain from [21,29] to [0,29] and you'll see what I mean. If the graph is fully zoomed-out [0,29], you can see the full gradient (white to green). When the graph is zoomed in [21,29], it also "zooms in" on the gradient, effectively making it disappear.
Is there a way to make the gradient be relative to the screen, so that the user continues to see the gradient regardless of the zoom?
I did try to convert the graph to Vega, and then try to scale the 0-1 gradient offset values based on the zoom, but it turned out rather complicated and messy. I'm wondering if I'm missing something, and if maybe there is a better way.
{
"$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==='MSFT'"}],
"mark": {
"type": "area",
"clip": true,
"line": {"color": "darkgreen"},
"color": {
"x1": 1,
"y1": 1,
"x2": 1,
"y2": 0,
"gradient": "linear",
"stops": [
{"offset": 0, "color": "white"},
{"offset": 1, "color": "darkgreen"}
]
}
},
"encoding": {
"x": {"field": "date", "type": "temporal", "scale": {"domain": ["2006-1-1", "2007-1-1-"]}},
"y": {"field": "price", "type": "quantitative", "scale": {"domain": [21, 29]}}
}
}

Related

Show negative values in Deneb column chart in red

I've been playing around with the Deneb visual in PowerBI Desktop and (amongst many other things) have been trying to create a simple column chart that shows negative values in red and positive values in green, however can't for the life of me seem to get it working - I believe the condition/test in my script is correct, but it refuses to 'fire' when it's 'true'
I've read through the condition page of the Vega-Lite documentation https://vega.github.io/vega-lite/docs/condition.html and have a condition section within the encoding/color
I've added Month End and MonthYear columns from my Calendar table and an EBITDA measure from a fact table to the Deneb visual
Month End
MonthYear
EBITDA
31/7/2021
"Jul-21"
8277.56
31/8/2021
"Aug-21"
-15123.66
30/9/2021
"Sep-21"
9502.11
31/10/2021
"Oct-21"
13090.99
{
"data": {"name": "dataset"},
"mark": "bar",
"encoding": {
"x": {
"field": "MonthYear",
"sort": {"field": "Month End"}
},
"y": {
"field": "EBITDA",
"aggregate": "sum"
},
"color": {
"condition": {
"test": "datum['EBITDA']<0",
"value": "red"
},
"value": "green"
}
}
}
If I adjust the condition to be "test": "1==1" then the 'true' path works, so I assume I've got something wrong with my test line, though this seems to be correct per a lot of blogs, stackoverflow questions etc.
I've also tried using a "tranform:" channel to create a new Neg field in the Deneb dataset and referring to that field in my test, but it still won't adjust the colour.
It doesn’t like your aggregation. It looks like the data you are sending in is already aggregated by Power BI. If so, this will work:
"y": {
"field": "b",
"type": "quantitative"
},
View sample in the Vega Editor
If your data isn’t aggregated, add an aggregate transform like this:
"transform": [
{"aggregate": [{
"op": "sum",
"field": "b",
"as": "bsum"
}],
"groupby": ["a"]}
],
"mark": "bar",
"encoding": {
"x": {
"field": "a",
"sort": {"field": "a"}
},
"y": {
"field": "bsum",
"type": "quantitative"
},
"color": {
"condition": {
"test": "datum['bsum']<0",
"value": "red"
},
"value": "green"
}
}
}
Open the Chart in the Vega Editor

Encode a Field using Conditions in Vega-Lite

OBJECTIVE
I'm trying to add data labels to my chart, however I have multiple bars layered on top of each other, and I need the data labels to hover over different bars depending on if values in a certain field are positive or negative.
ATTEMPT
This could be achieved by changing the "field" property of the "y" encoding using a condition. I've spent some time exploring Vega-Lite documentation and experimenting with some stuff, but I can't get it to work no matter what I try. Vega seems to ignore by condition. I'm also curious if I'm able to apply conditions to "mark" rather than "encoding". When values are negative, I'd like to change "dy" to 10 from -10.
Any suggestions?
'''
"mark": {
"type":"text",
"dy":-10
},
"encoding": {
"text": {
"field": "field_one"
},
"y": {
"condition":{
"test":"datum['test_data'] < 0",
"field": "field_one"
},
"field": "field_two"
}....
}
'''
A couple solutions exist.
Two Text Encodings:
One solution is to create two texts with varying y offsets and fields, and hide them depending on whether the values are positive or negative.
{
"mark": {
"type":"text",
"dy":-10
},
"encoding": {
"text": {
"condition":{
"test": "datum['test_data'] >= 0",
"type":"quantitative",
"field": "test_data"
}
"value": ""
},
"y": {
"field": "field_one",
"type": "quantitative"
}
}
},
{
"mark": {
"type":"text",
"dy":10
},
"encoding": {
"text": {
"condition":{
"test": "datum['test_data'] < 0",
"type":"quantitative",
"field": "test_data"
}
"value": ""
},
"y": {
"field": "field_two",
"type": "quantitative"
}
}
}
Transformation and Calculation
The other solution only solves the "dy" problem and was answered using another technique involving transform and calculate on GitHub.

Deneb plot (Vega-Lite) for Power BI: How to use an free scale y-axis with facet

I am using Deneb custom visual to repeat visual for different tasks. Is it possible to only show the relevent Y-axis values. Following data is used:
The following Vega-lite JSON is used:
{
"data": {"name": "dataset"},
"mark": {
"type": "bar",
"opacity": 1,
"tooltip": true,
"cornerRadius": 15
},
"encoding": {
"x": {
"field": "Earliest StartDate",
"type": "temporal"
},
"y": {
"field": "MachGrpCode",
"type": "nominal",
"axis": {
"title": null,
"grid": true,
"tickBand": "extent"
}
},
"row": {
"field": "ProdHeaderOrdNr",
"header": {"labelAngle": 0}
}
},
"resolve": {
"axis": {
"x": "independent",
"y": "independent"
}
}
}
Which results in:
Is it possible to only use the relevent task values (for 022 --> erase 6700 row)?
From what I've seen, this is a Vega bug. The recommended work-around is to use vconcat with a filter transform. If you only have a few ProdHeaderOrdNr, this is doable.
Open the Chart in the Vega Editor

How do I query an AWS OpenSearch index using a Vega visualization?

I have data in an index in JSON format, and I want to use a Vega visualization to display this (full Vega, not Vega-Lite). I've found however that every example out there is for Vega-Lite and all they're trying to do it stick their data into a time series graph. I'd like to do something different, and thus I find myself at a dead-end.
A sample doc in my index:
{
"_index": "myindex",
"_type": "doc",
"_id": "abc123",
"_version": 1,
"_score": null,
"timestamp": "2022-05-23T07:43:21.123Z",
"_source": {
"fruit": [{
"amount": 15,
"type": {
"grower_id": 47,
"grower_country": "US",
"name": "apple"
}
},
{
"amount": 43,
"type": {
"grower_id": 47,
"grower_country": "CAN",
"name": "apple"
}
},
{
"amount": 7,
"type": {
"grower_id": 23,
"grower_country": "US",
"name": "orange"
}
},
{
"amount": 14,
"type": {
"grower_id": 23,
"grower_country": "CAN",
"name": "orange"
}
}
]
}
}
What I want to do is create 2 text marks on the visualization that will display the sum of the values as follows.
Symbol1 = sum of all apples (i.e. all apples grown in the US and CAN combined)
Symbol2 = sum of all oranges (i.e. all oranges grown in the US and CAN combined)
I tried the following data element with no success:
"data": [{
"name": "mydata",
"url": {
"index": "myindex",
"body": {
"query": "fruit.type.name:'apple'",
},
}
}
]
However obviously this query isn't even correct. What I want to be able to do is return a table of values and then be able to use those values in my marks as values to drive the mark behaviour or color. I'm comfortable with doing the latter in Vega, but getting the data queried is where I'm stuck.
I've read and watched so many tutorials which cover Vega-Lite, but I'm yet to find a single working example for Vega on AWS OpenSearch.
Can anyone please help?

Is there a way to set the extent parameter of a bin dynamically (histogram)?

I'm using vega-lite in PBI and I'm trying to create a histogram in which its X-axis range changes dynamically acording to two fields (Start, End) from a table of my PBI, this two fields repeat in each record as can be seen in image.
PBI
The examples of extent in the documentation I found used only numbers, so my initial code is this:
initial code
Yet I'm trying to do following code:
{
"data": {"name": "dataset"},
"mark": {
"type": "bar",
"tooltip": true
},
"encoding": {
"x": {
"bin": {
"extent": [
{"field": "Start"},
{"field": "End"}
],
"step": 1
},
"field": "Actual"
},
"y": {"aggregate": "count"}
}
}
But it throws a lot of warnings, and in the end it does nothing:
error
Thanks.
Setting bin extent based on field name is not supported. Per the Vega-lite docs, bin.range is
A two-element ([min, max]) array indicating the range of desired bin values.
where min and max are each numbers.
As to your specific use-case: I would suggest filtering out the data points that fall outside the range you want to ignore. filter docs.
Your filter might look something like this (this will drop all points outside of the extent you specified)
{
"transform": [
{
"filter": {
"not": {"field": "Actual", "range": [25, 45]} }
}
}
],
...
}
If you need [25, 45] to be dynamic, you can set them using an ExprRef instead of using a number, like this
"range": [
{"expr": "datum.Start"},
{"expr": "datum.End"}
]