How to show Vega visualizations in Google Colab - google-colaboratory

I can use Altair to show Vega-Lite visualizations in Google Colab. But is there a way to show plain Vega visualizations?
I tried ipyvega in Google Colab. But when I run their example in Google Colab, then nothing shows up, and there is no error.

You can display a vega chart in Colab using the altair.vega.Vega class, once you have enabled the Colab renderer.
Here is an example:
from urllib import request
import json
with request.urlopen("https://vega.github.io/vega/examples/bar-chart.vg.json") as f:
spec = json.load(f)
from altair import vega
vega.renderers.enable('colab')
vega.Vega(spec)

You can use vega magic from altair. But it needs some setup.
# setup
!pip -q install -U PyYAML
from altair.vega import Vega
Vega.renderers.enable('colab')
%load_ext altair
Then use the %%vega magic.
%%vega
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 400,
"height": 200,
"data": [
{
"name": "table",
"values": [
{"category": "A", "amount": 28},
{"category": "B", "amount": 55},
{"category": "C", "amount": 43},
{"category": "D", "amount": 91},
]
}
],
"scales": [
{
"name": "xscale",
"type": "band",
"domain": {"data": "table", "field": "category"},
"range": "width",
},
{
"name": "yscale",
"domain": {"data": "table", "field": "amount"},
"range": "height"
}
],
"axes": [
{ "orient": "bottom", "scale": "xscale" },
{ "orient": "left" , "scale": "yscale" }
],
"marks": [
{
"type": "rect",
"from": {"data":"table"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "category"},
"width": {"scale": "xscale", "band": 1},
"y": {"scale": "yscale", "field": "amount"},
"y2": {"scale": "yscale", "value": 0}
},
}
}
]
}
The simple bar chart is then displayed.
If the vega spec is already in a dict, using Vega(spec) is easier.
from requests import get
url = 'https://vega.github.io/vega/examples/bar-chart.vg.json'
spec = get(url).json()
Vega(spec)

Related

Labels on Rects in Vega Stacked Bar Chart

In the old vega-label documentation there is reference to a labeled stacked bar chart example. The example spec doesn’t work in the online Vega editor, throwing an error that a.map is not a function.
I am trying to do almost exactly what is referenced in the above example: create a vertically-stacked bar chart where each segment is labeled with its value. I have seen a few examples of this in Vega-Lite with layers, but how can it be achieved in Vega?
I’ve attempted to recreate the above spec using a group containing the rect mark and the text mark, but I’m not getting it right. I also see how to display the value as a tooltip on hover, but I’d like it displayed in the rectangle of each segment of the bar itself.
Ideally I would end up with a chart like this:
Here’s the spec I’ve been working with:
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A basic stacked bar chart example.",
"width": 294,
"height": 200,
"padding": 5,
"autosize": {"type": "fit-x", "contains": "padding"},
"data": [
{
"name": "categories",
"values": [
{"y": 5, "c": 0, "name": "other"},
{"y": 7, "c": 1, "name": "corn"},
{"y": 22, "c": 2, "name": "pasture/hay"},
{"y": 31, "c": 3, "name": "developed"},
{"y": 35, "c": 4, "name": "forest"}
],
"transform": [
{
"type": "stack",
"field": "y"
}
]
}
],
"scales": [
{
"name": "y",
"type": "linear",
"range": "height",
"nice": true, "zero": true,
"domain": {"data": "categories", "field": "y1"}
},
{
"name": "color",
"type": "ordinal",
"range": "category",
"domain": {"data": "categories", "field": "c"}
}
],
"axes": [
],
"marks": [
{
"name": "categoriesBars",
"type": "group",
"from": {"data": "categories"},
"zindex": 1,
"marks": [
{
"type": "rect",
"from": {"data": "categories"},
"encode": {
"enter": {
"x": {"value": 0},
"width": {"value": 294},
"y": {"scale": "y", "field": "y0"},
"y2": {"scale": "y", "field": "y1"},
"fill": {"scale": "color", "field": "c"}
},
"update": {
"fillOpacity": {"value": 1}
},
"hover": {
"fillOpacity": {"value": 0.5}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"y": {"field": {"parent": "y"}},
"x": {"value": 130},
"fill": [
{"test": "contrast('white', datum.fill) > contrast('black', datum.fill)", "value": "white"},
{"value": "black"}
],
"align": {"value": "center"},
"baseline": {"value": "middle"},
"text": {"field": {"parent": "name"}}
}
}
}
]
}
]
}
Is this what you're after?
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A basic stacked bar chart example.",
"width": 294,
"height": 200,
"padding": 5,
"autosize": {"type": "fit-x", "contains": "padding"},
"data": [
{
"name": "categories",
"values": [
{"y": 5, "c": 0, "name": "other"},
{"y": 7, "c": 1, "name": "corn"},
{"y": 22, "c": 2, "name": "pasture/hay"},
{"y": 31, "c": 3, "name": "developed"},
{"y": 35, "c": 4, "name": "forest"}
],
"transform": [{"type": "stack", "field": "y"}]
}
],
"scales": [
{
"name": "y",
"type": "linear",
"range": "height",
"nice": true,
"zero": true,
"domain": {"data": "categories", "field": "y1"}
},
{
"name": "color",
"type": "ordinal",
"range": {"scheme": "pastel2"},
"domain": {"data": "categories", "field": "c"}
}
],
"axes": [],
"marks": [
{
"name": "i",
"type": "rect",
"from": {"data": "categories"},
"encode": {
"enter": {
"x": {"value": 0},
"width": {"value": 294},
"y": {"scale": "y", "field": "y0"},
"y2": {"scale": "y", "field": "y1"},
"fill": {"scale": "color", "field": "c"}
},
"update": {"fillOpacity": {"value": 1}},
"hover": {"fillOpacity": {"value": 0.5}}
}
},
{
"type": "text",
"from": {"data": "i"},
"encode": {
"update": {
"y": {"field": "y"},
"dy": {"signal": "(datum.y2 - datum.y)/2"},
"x": {"signal": "width/2"},
"fill": [
{
"test": "contrast('white', datum.fill) > contrast('black', datum.fill)",
"value": "white"
},
{"value": "black"}
],
"align": {"value": "center"},
"baseline": {"value": "middle"},
"text": {"field": "datum.name"}
}
}
}
]
}

Vega Wordcloud Faceting

i really like the look of the vega Word Clouds:
https://vega.github.io/vega/examples/word-cloud/
I'm currently using the spec from the link as follows in colab:
spec = "insert spec here"
#Option one:
from altair import vega
vega.renderers.enable('colab')
vega.Vega(spec)
#Option two:
import panel as pn
from vega import Vega
pn.extension('vega')
pn.pane.Vega(spec)
But actually i want to make faceted wordclouds with vega. I currently load my data as json from my github account which is also slightly annoying, but i found no way to reference python variables in the vega spec.
Does anyone maybe have a hint, how i could layout the vega wordcloud in a grid by groups specified in my data? My json has this structure: [{"text":text,"group":group}], drawing the wordclouds from this works, but not the faceting by the group field. I know vega-lite can do faceting, but it can't draw the beautiful wordcloud it seems.
Thanks for any help!
Here is a working example of Vega spec using facet with your data.
For illustration only, the formula field for angle places words with larger field size in horizontal position.
View in Vega online editor
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A word cloud visualization depicting Vega research paper abstracts.",
"title": "A Wordcloud",
"width": 400,
"height": 400,
"padding": 10,
"background": "ghostwhite",
"layout": {
"bounds": "flush",
"columns": 2,
"padding": 10
},
"data": [
{
"name": "table",
"url": "https://raw.githubusercontent.com/nyanxo/vega_facet_wordcloud/main/split.json",
"transform": [
{
"type": "formula",
"as": "angle",
"expr": "datum.size >= 3 ? 0 : [-45,-30, -15, 0, 15, 30, 45][floor(random() * 7)]"
}
]
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {"data": "table", "field": "text_split"},
"range": ["#d5a928", "#652c90", "#939597"]
}
],
"marks": [
{
"type": "group",
"from": {
"facet": {
"name": "facet",
"data": "table",
"groupby": "group"
}
},
"title": {
"text": {"signal": "parent.group"},
"frame": "group"
},
"encode": {
"update": {
"width": {"signal": "width"},
"height": {"signal": "height"}
}
},
"marks": [
{
"type": "rect",
"encode": {
"enter": {
"x": {"value": 0},
"width": {"signal": "width" },
"y": {"value": 0},
"height": {"signal": "height"},
"fill": {"value": "beige"}
}
}
},
{
"type": "text",
"from": {"data": "facet"},
"encode": {
"enter": {
"text": {"field": "text_split"},
"align": {"value": "center"},
"baseline": {"value": "alphabetic"},
"fill": {"scale": "color", "field": "text_split"}
},
"update": {"fillOpacity": {"value": 1}},
"hover": {"fillOpacity": {"value": 0.5}}
},
"transform": [
{
"type": "wordcloud",
"size": {"signal": "[width, height]"},
"text": {"field": "text_split"},
"rotate": {"field": "datum.angle"},
"font": "Helvetica Neue, Arial",
"fontSize": {"field": "datum.size"},
"fontSizeRange": [12, 28],
"padding": 2
}
]
}
]
}
]
}
You can't facet a word cloud as it requires a CountPattern transform which will destroy any faceting field you try to use. Instead you will need to provide a separate data object for each word cloud you want and then concatenate them together.
Edit
Link
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A word cloud visualization depicting Vega research paper abstracts.",
"title": "A Wordcloud",
"width": 420,
"height": 400,
"padding": 0,
"data": [
{
"name": "table",
"url": "https://raw.githubusercontent.com/nyanxo/vega_facet_wordcloud/main/split.json"
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {"data": "table", "field": "text_split"},
"range": ["#d5a928", "#652c90", "#939597"]
}
],
"layout": {"padding": 20, "columns": 2, "bounds": "full", "align": "all"},
"marks": [
{
"name": "cell",
"type": "group",
"style": "cell",
"from": {
"facet": {"name": "facet", "data": "table", "groupby": ["group"]}
},
"encode": {
"update": {"width": {"signal": "400"}, "height": {"signal": "400"}}
},
"marks": [
{
"type": "text",
"from": {"data": "facet"},
"encode": {
"enter": {
"text": {"field": "text_split"},
"align": {"value": "center"},
"baseline": {"value": "alphabetic"},
"fill": {"scale": "color", "field": "text_split"}
},
"update": {"fillOpacity": {"value": 1}},
"hover": {"fillOpacity": {"value": 0.5}}
},
"transform": [
{
"type": "wordcloud",
"size": [400, 400],
"text": {"field": "text_split"},
"font": "Helvetica Neue, Arial",
"fontSizeRange": [12, 56],
"padding": 2
}
]
}
]
}
]
}

The display of a signal element in the Vega visualization within a Kibana dashboard is not fully displayed using autosize

I want to have a display of Vega in Kibana, with the autosize active to be able to adjust it to any size in a dashboard, but I can't get it to show me the signal (radio type) without having to use the scroll bar.
Here I show an example code where you can see the problem I have. In this case, I don't have the signal linked to anything yet, because what I need to solve first is that it can be seen easily, without the need to use a scroll:
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"data": [
{
"name": "table",
"values": [
{"category": "A", "amount": 28},
{"category": "B", "amount": 55},
{"category": "C", "amount": 43},
{"category": "D", "amount": 91},
{"category": "E", "amount": 81},
{"category": "F", "amount": 53},
{"category": "G", "amount": 19},
{"category": "H", "amount": 87}
]
}
],
"signals": [
{
"name": "radio_signal", "value": "ALL",
"bind": {"input": "radio", "options": ["ALL", "OK", "NOK"]}
},
{
"name": "tooltip",
"value": {},
"on": [
{"events": "rect:mouseover", "update": "datum"},
{"events": "rect:mouseout", "update": "{}"}
]
}
],
"scales": [
{
"name": "xscale",
"type": "band",
"domain": {"data": "table", "field": "category"},
"range": "width",
"padding": 0.05,
"round": true
},
{
"name": "yscale",
"domain": {"data": "table", "field": "amount"},
"nice": true,
"range": "height"
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"title": "X-Axis",
},
{ "orient": "left",
"scale": "yscale",
"title": "Y-Axis",
"tickCount": 4,"offset": 6 }
],
"marks": [
{
"type": "rect",
"from": {"data":"table"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "category"},
"width": {"scale": "xscale", "band": 1},
"y": {"scale": "yscale", "field": "amount"},
"y2": {"scale": "yscale", "value": 0}
},
"update": {
"fill": {"value": "steelblue"}
},
"hover": {
"fill": {"value": "red"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"align": {"value": "center"},
"baseline": {"value": "bottom"},
"fill": {"value": "#333"}
},
"update": {
"x": {"scale": "xscale", "signal": "tooltip.category", "band": 0.5},
"y": {"scale": "yscale", "signal": "tooltip.amount", "offset": -2},
"text": {"signal": "tooltip.amount"},
"fillOpacity": [
{"test": "isNaN(tooltip.amount)", "value": 0},
{"value": 1}
]
}
}
}
]
}
You need to slightly adjust the height and width signals by 10 to 20 depending on how long the names of your radio signals are, this will essentially zoom out your visualisation slightly. I've had instances where I need to subtract 40 so play around with this value a bit. For example try adding this to the signal spec...
...
signals: [
...
{
height: height - 10
}
{
width: width -10
}
...
]
...

Vega transformation sample

This sample code from vega transformations is not working.
I am not getting the expected results.
Can you please help me run this example in the vega editor?
[
{"foo": {"a": 5, "b": "abc"}, "bar": 0},
{"foo": {"a": 6, "b": "def"}, "bar": 1},
{"foo": {"a": 7, "b": "ghi"}, "bar": 2}
]
To extract the "bar" field along with the "a" and "b" sub-fields into new objects, use the transform:
{
"type": "project",
"fields": ["bar", "foo.a", "foo.b"],
"as": ["bar", "a", "b"]
}
This produces the following output:
[
{"bar":0, "a":5, "b":"abc"},
{"bar":1, "a":6, "b":"def"},
{"bar":2, "a":7, "b":"ghi"}
]
Ok, I used the very first sample in the editor (the bar chart one) to demonstrate the transformation for you. Here is the modified code you can paste in the editor:
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A basic bar chart example, with value labels shown upon mouse hover.",
"width": 400,
"height": 200,
"padding": 5,
"data": [
{
"name": "table",
"values": [
{"foo": {"a": 5, "b": "abc"}, "bar": 0},
{"foo": {"a": 6, "b": "def"}, "bar": 1},
{"foo": {"a": 7, "b": "ghi"}, "bar": 2}
],
"transform": [
{
"type": "project",
"fields": ["bar", "foo.a", "foo.b"],
"as": ["bar", "a", "b"]
}
]
}
],
"signals": [
{
"name": "tooltip",
"value": {},
"on": [
{"events": "rect:mouseover", "update": "datum"},
{"events": "rect:mouseout", "update": "{}"}
]
}
],
"scales": [
{
"name": "xscale",
"type": "band",
"domain": {"data": "table", "field": "bar"},
"range": "width",
"padding": 0.05,
"round": true
},
{
"name": "yscale",
"domain": {"data": "table", "field": "a"},
"nice": true,
"range": "height"
}
],
"axes": [
{ "orient": "bottom", "scale": "xscale" },
{ "orient": "left", "scale": "yscale" }
],
"marks": [
{
"type": "rect",
"from": {"data":"table"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "bar"},
"width": {"scale": "xscale", "band": 1},
"y": {"scale": "yscale", "field": "a"},
"y2": {"scale": "yscale", "value": 0}
},
"update": {
"fill": {"value": "steelblue"}
},
"hover": {
"fill": {"value": "red"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"align": {"value": "center"},
"baseline": {"value": "bottom"},
"fill": {"value": "#333"}
},
"update": {
"x": {"scale": "xscale", "signal": "tooltip.bar", "band": 0.5},
"y": {"scale": "yscale", "signal": "tooltip.a", "offset": -2},
"text": {"signal": "tooltip.b"},
"fillOpacity": [
{"test": "datum === tooltip", "value": 0},
{"value": 1}
]
}
}
}
]
}
And here would be the expected result:
As you can see in the data viewer of the editor, "bar" "a" and "b" have the correct values, and I have changed the bar chart so it uses those values to show the bars, the appropriate height, as well as the tooltip when you hover over a bar.

How to create a stacked bar chart with values in Vega?

I'm creating a custom visualization in Vega for Kibana. It should display vertical stacked bars and their values in numbers.
The "y" axis is the doc count and the "x" axis a time scale.
I'm not familiar with Vega and I first tried to display numbers on simple bars. I copy/pasted, tweeked some parameters and had this version :
"marks": [
{
"type": "group",
"marks": [
{
"type": "rect",
"name": "bars",
"from": {"data":"table"},
"encode": {
"enter": {
"x": {"scale": "xbars", "field": "key"},
"width": {"scale": "xbars", "band": 1},
"y": {"scale": "yscale", "field": "doc_count"},
"y2": {"scale": "yscale", "value": 0}
}
}
},
{
"type": "text",
"from": {"data": "bars"},
"align": "center",
"encode": {
"enter": {
"y": {"field": "y", "offset": -5},
"x": {"field": "x", "offset": 0},
"text": {"field": "datum.doc_count"}
}
}
}
]
}
]
The result displays simple bars, numbers, the time format is good.
I used a "y"and a "y2" to be able to display both bars and text, but I can't add anymore "y" axis ("y3", "y4"...).
Idon't even know if it's possible to do what I want.
It want the chart to look like this example but with numbers :
https://vega.github.io/vega/examples/stacked-bar-chart/