Force vega-lite to show label when number is 0 - vega-lite

I'm still very much a beginner in vega-lite but I'm trying to create a stacked bar chart with different sales channels. Sometimes a sales channel has a 0 and doesn't show up, how can I still show the label?
{
"layer": [
{
"mark": {
"type": "bar",
"cornerRadius": 50,
"color": "#90C290",
"tooltip": true
},
"encoding": {
"x": {
"field": "Number of customers"
}
}
},
{
"mark": {
"type": "text",
"tooltip": true,
"align": "left",
"baseline": "middle",
"x": 10,
"color": "white"
},
"encoding": {
"text": {
"field": "Number of customers",
"type": "text"
}
}
}
],
"encoding": {
"y": {
"field": "Sales channel",
"type": "nominal",
"sort": "descending",
"title": null
},
"x": {
"type": "quantitative",
"title": null,
"axis": null
}
}
}
I tried the code above and looked through documentation but couldn't exactly find what I was looking for

I added sample data to your spec, and there are a few changes I would make.
Around line 29 you have "type": "text" which should be "type": "quantitative".
I think your problem is that the text color is white and the background color is white, so the text is there but you can't see it. A simple fix would be to set the text color to black, or change the background color to something other than white (add "background": "lightgray", before "layer").
It's also possible you don't see the channel at all depending on how you are passing data from Power BI. Check the data tab in the Deneb window to make sure the Channel is there.
If the channel is not there, you'll have to adjust something on the Power BI side. A good practice is to put the data in a table in Power BI first so you know what you are sending into Deneb. If you use an aggregation like SUM on the data field in Power BI, nulls will drop out, but zeros should stay. If you use "Don't summarize" then nulls or errors (text in a number field) will pass in as nulls to Deneb, but you may need to add an "aggregate": "sum" to your encoding.
In any case, here's the spec the way I would write it.
{
"data": {"name": "dataset"},
"layer": [
{
"mark": {
"type": "bar",
"cornerRadius": 50,
"color": "#90C290",
"tooltip": true
}
},
{
"mark": {
"type": "text",
"tooltip": true,
"align": "left",
"baseline": "middle",
"dx": 5,
"color": "black"
},
"encoding": {
"text": {
"field": "Number of customers",
"type": "quantitative"
}
}
}
],
"encoding": {
"y": {
"field": "Sales channel",
"type": "nominal",
"sort": "descending",
"title": null
},
"x": {
"field": "Number of customers",
"type": "quantitative",
"title": null,
"axis": null
}
}
}
Link to sample data in Vega Editor

Related

how to make marker for tooltip bigger

Here's my wandb vega. The problem is, right now, it is very hard to mouse over my line and get the tooltip to show. It is like you must hover over the exact pixel of the line with your mouse. How do I make the activation radius larger, so my tooltip shows up if I am approximately on top of the point of my line?
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A plot for an arbitrary number of lines",
"data": {
"name": "wandb"
},
"transform": [
{"filter": {"field": "${field:lineVal}", "valid": true}},
{"filter": {"field": "${field:step}", "valid": true}}
],
"title": "${string:title}",
"layer": [
{
"selection": {
"grid": {
"type": "interval",
"bind": "scales"
}
},
"mark": {"type": "line", "strokeWidth": 5, "interpolate": "linear", "tooltip": true},
"encoding": {
"x":{
"field": "${field:step}",
"type": "quantitative",
"title": "${string:xname}"
},
"y": {
"field": "${field:lineVal}",
"title": "y",
"type": "quantitative"
},
"color": {
"type": "nominal",
"field": "${field:lineKey}"
},
"strokeDash": {
"type": "nominal",
"field": "name"
}
}
}
]
}
You haven't provided the data along with your schema so it is difficult to answer your specific case. However, you should be able to adapt the example code from https://vega.github.io/vega-lite/examples/interactive_multi_line_pivot_tooltip.html to achieve what you want.

how to layer multiple regression lines without repeating code?

I'm using Vega Lite to chart the times at which I eat my meals, and want a regression (loess) line showing the general time for each. By default, a regression uses the entire dataset and only shows one line; I want three lines, one for each meal (stored in the field extra_data.content).
I've achieved what I want to do my repeating the loess layer three times (screenshot) but am trying to find a solution in which the same layer is written once and repeats itself three times.
Edit after solving! Thanks very much to #jakevdp for the answer! Here is my working code; note that there is both a groupby on the loess and a color channel.
{
"mark": "line",
"transform": [
{
"loess": "hm",
"on": "ymd",
"groupby": ["extra_data.content"]
}
],
"encoding": {
"x": {
"field": "ymd",
"type": "temporal"
},
"y": {
"field": "hm",
"type": "temporal"
},
"color": {
"field": "extra_data.content",
"type": "nominal"
}
}
}
It sounds like you want the groupby argument of the loess transform, along with a color encoding. It might look something like this:
{
"mark": "line",
"transform": [
{
"loess": "hm",
"on": "ymd",
"groupby": ["extradata.content"]
}
],
"encoding": {
"x": {
"field": "ymd",
"type": "temporal"
},
"y": {
"field": "hm",
"type": "temporal"
},
"color": {
"field": "extradata.content",
"type": "nominal"
}
}
}

plot small multiples in vega-lite with gray background

I'm looking for a vega-lite configuration to show small multiples (using the facet operator row or column) with all other data points greyed out in the background.
Here is an example plot using the facet-operator:
facet plot
in vega-editor
"facet": {
"row": {
"field": "group",
"type": "nominal"
}
},
And here is an example using multiple charts with the concat operator and color channel to grey out other groups:
concat-plot
in vega-editor
"color": {"condition": {"test": "datum['group'] != 1", "value": "grey"}, "value": "red"}
I was wondering if there is a combination of transforms and repeat commands to achieve this for an unknown number of groups.
Here is one possible solution:
create an additional layer with new data
"facet": {"row": {"field": "group"}},
"spec": {
"layer": [
{
"data": {"name": "main"},
"mark": "circle",
"encoding": {
"y": {
"field": "y",
"type": "ordinal"
},
"x": {
"field": "x",
"type": "ordinal"
},
"color": {"value": "grey"}
},
"params": []
},
{
"mark": {"type": "circle", "opacity": 1, "color": "red"},
"encoding": {
"y": {
"field": "y",
"type": "ordinal"
},
"x": {
"field": "x",
"type": "ordinal"
}
}
}
]
}
full example in vega editor

Is it possible to apply the same condition as color encoding for legend

My source code is following
"transform": [
{
"window": [
{
"op": "rank", "field": "Value", "as": "_rank"
}
],
"sort": [
{
"field": "Value",
"order": "descending"
}
]
}
],
"encoding": {
"color": {
"field": "_rank",
"condition": {
"test": "datum._rank>5",
"value": "grey"
}
},
"x": {
"field": "Week",
"type": "nominal",
"axis": {
"labelAngle": 0
}
},
"y": {
"field": "Value",
"type": "quantitative",
"axis": {
"grid": false
}
}
},
"layer": [
{
"mark": {
"type": "bar",
"tooltip": true
}
},
{
"mark": {
"type": "text",
"align": "center",
"baseline": "middle",
"dx": 0,
"dy": -5,
"tooltip": true
},
"encoding": {
"text": {
"field": "Value"
}
}
}
]
I put a condition for the color encoding to show anything but top5 to show in different colors and any values that are not top5 should be grey.
"color": {
"field": "_rank",
"condition": {
"test": "datum._rank>5",
"value": "grey"
}
}
It is all good for the bars but the legends don't generate with the same conditions.
Is it possible to extend the same top5 logics for the legend's color as well? i.e. anything <5 are grey in color (each) in legend and everything else is the same color as the condition (currently this part is getting generated)
Editor
The legend colors will reflect the color scale that you specify, and not reflect conditions.
The easiest way to do what you want is likely by setting the range for your color scheme; for example:
{
"data": {"url": "data/cars.json"},
"mark": "point",
"encoding": {
"x": {"field": "Horsepower", "type": "quantitative"},
"y": {"field": "Miles_per_Gallon", "type": "quantitative"},
"color": {
"field": "Origin", "type": "nominal",
"scale": {"range": ["purple", "#ff0000", "teal"]}
}
}
}
You'll have to modify the specified colors based on how many color categories you have in your data.

Vega-lite interactive legend and bar chart

I'm fairly new to vega-lite. I'd really like to get the following interactive bar chart working:
Legend for the bar chart that can be clicked on to highlight one or more bars
Click on one or more bars to highlight and reflect that it legend
When highlighed, show text value above the bar.
My strategy for building this is to have two layers, one layer for the bars, and one for the text. Then one selection that is in 'multi' mode on mousedown, and also bound to the legend.
My question is two-fold:
Is it possible to have a selection bound to the legend but also utilize mousedown?
I'm having a hard time understanding how selections work in layered graphs/charts. If I define the selection outside of the layers I get a warning saying selection can't be found, and the selection only works as expected if I put it in the definition of the first layer. Additionally, the legend binding seems to work if I don't have layers, but stops working when I do have layers. Is this a limitation of the library or am I doing something wrong.
Here is my schema, thanks for any help in advance!
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"description": "A simple bar chart with embedded data.",
"title": "test",
"data": {
"values": [
["Lateral", 630.666127],
["Basal", 413.211154],
["Accessory", 257.842981],
["Anterior", 48.735523],
["Central", 45.797799],
["Medial", 30.314856],
["Cortical", 27.697457],
["Corticoamygdaloid", 169.707268],
["Paralaminar", 46.216784],
["Whole_amygdala", 1670.189948]
],
"name": "data"
},
"width": "600",
"height": "400",
"encoding": {
"x": {"field": "0", "type": "nominal", "sort": "-y"},
"y": {"field": "1", "type": "quantitative"}
},
"layer": [
{
"mark": "bar",
"encoding": {
"color": {
"field": "0"
},
"opacity": {
"condition": {"selection": "series", "value": 1},
"value": 0.2
}
},
"selection": {
"series": {"type": "multi", "bind": "legend"}
}
},
{
"transform": [{"filter": {"selection":"series"}}],
"mark": {"type": "text", "dy": -5},
"encoding": {"text": {"field": "1"}}
}
]
}
You were quite close. When you bind a selection to a legend, by default it deactivates other ways of interacting. But as mentioned briefly in the Legend Binding docs, you can re-enable this by specifying the "on" attribute. Here is the result (Open in editor):
{
"title": "test",
"data": {
"values": [
["Lateral", 630.666127],
["Basal", 413.211154],
["Accessory", 257.842981],
["Anterior", 48.735523],
["Central", 45.797799],
["Medial", 30.314856],
["Cortical", 27.697457],
["Corticoamygdaloid", 169.707268],
["Paralaminar", 46.216784],
["Whole_amygdala", 1670.189948]
],
"name": "data"
},
"width": "600",
"height": "400",
"encoding": {
"x": {"field": "0", "type": "nominal", "sort": "-y"},
"y": {"field": "1", "type": "quantitative"}
},
"layer": [
{
"mark": "bar",
"encoding": {
"color": {"field": "0"},
"opacity": {
"condition": {"selection": "series", "value": 1},
"value": 0.2
}
},
"selection": {
"series": {
"type": "multi",
"encodings": ["color"],
"on": "click",
"bind": "legend"
}
}
},
{
"transform": [{"filter": {"selection": "series"}}],
"mark": {"type": "text", "dy": -5},
"encoding": {"text": {"field": "1"}}
}
]
}
Regarding your second question: currently selections must be defined within the layers they are bound to, but this will likely change in future Vega-Lite versions; see https://github.com/vega/vega-lite/pull/6919.