Building Blocks of a Vega-Lite Visualization
The data
, mark
and encoding
properties of a Vega-Lite specification are the basic building blocks of a Vega-Lite visualization. In the Deneb.jl, sub-specifications for these properties can conveniently be defined using Data
, Mark
, and Encoding
and then composed using the *
operator to build the final specification.
using Deneb
cars = "https://vega.github.io/vega-datasets/data/cars.json"
Data(url=cars) * Mark(:point) * Encoding(
"Horsepower:q",
"Miles_per_Gallon:q",
color=:Origin
)
Data
Similar to Vega-Lite, in Deneb.jl a dataset can be defined in several ways:
- as tabular data,
- as a URL from which to load the data,
- or as any of Vega-Lite's data generators.
Tabular data
Deneb.jl accepts any tabular data that supports the Tables.jl interface (e.g. DataFrames.jl or any of these formats) by simply passing the data to Data
.
data = (a=[1, 2], b=["potato", "tomato"])
Data(data)
Deneb.DataSpec:
{
"values": [
{
"a": 1,
"b": "potato"
},
{
"a": 2,
"b": "tomato"
}
]
}
In the example above the source data was simply a NamedTuple
, but it could've been for instance a DataFrame
.
using DataFrames
Data(DataFrame(data))
Deneb.DataSpec:
{
"values": [
{
"a": 1,
"b": "potato"
},
{
"a": 2,
"b": "tomato"
}
]
}
As shown in the output, Deneb.jl internally transforms this data into an appropriate spec with a format that Vega-Lite can interpret.
Data from a URL
Alternatively, data can be loaded from a URL using the url
keyword argument.
Data(url="https://vega.github.io/vega-datasets/data/cars.json")
Deneb.DataSpec:
{
"url": "https://vega.github.io/vega-datasets/data/cars.json"
}
Other properties can be specified to ensure that the loaded data is correctly parsed by Vega-Lite.
Data(
url="https://vega.github.io/vega-datasets/data/us-10m.json",
format=(type=:topojson, feature=:states),
)
Deneb.DataSpec:
{
"url": "https://vega.github.io/vega-datasets/data/us-10m.json",
"format": {
"type": "topojson",
"feature": "states"
}
}
To learn more about the formats accepted by Vega-Lite and the properties describing a data source from URL, refer to Vega-Lite's documentation.
Data generators
Deneb.jl also provides a simple API to define data using any of the data generators available in Vega-Lite. The generator type (currently Vega-Lite provides a sequence
, a graticule
and a sphere
generator) can be specified as a positional argument of type String
or Symbol
, while the properties defining the generator can be specified as keyword arguments.
Data(
:graticule, step=[15, 15]
) * Mark(:geoshape) * projection(
:orthographic, rotate=[0, -45, 0]
)
Mark
The mark
property of a Vega-Lite specification can be defined in Deneb.jl using Mark
, where the positional argument defines the mark
type (point
, bar
, line
,...) as a String
or a Symbol
.
Mark(:errorband)
Deneb.MarkSpec:
{
"type": "errorband"
}
And the the keyword arguments define the other optional properties of the mark.
Mark(:errorband, extent=:ci, borders=(opacity=0.5, strokeDash=[6, 4]))
Deneb.MarkSpec:
{
"type": "errorband",
"extent": "ci",
"borders": {
"opacity": 0.5,
"strokeDash": [
6,
4
]
}
}
Refer to Vega-Lite's documentation to learn more about the mark types and their properties.
Encoding
The encoding
property of a single view specification represents the mapping between encoding channels (such as x
, y
, or color
) and data fields. In Deneb.jl the encoding
is defined with Encoding
, which can optionally take one or two positional arguments representing the the x
and y
channels, and any number of keyword arguments representing any arbitrary Vega-Lite channel (including explicit x
/y
channels). In the simplest scenario the arguments are of type String
or Symbol
representing the field
property of the given encoding channel.
Encoding(:Horsepower, :Miles_per_Gallon, color=:Origin)
Deneb.EncodingSpec:
{
"color": {
"field": "Origin"
},
"x": {
"field": "Horsepower"
},
"y": {
"field": "Miles_per_Gallon"
}
}
Shorthand string syntax
Similar to Altair, the encoding channels can be defined with a shorthand string syntax to conveniently define the field
, the type
and the aggregate
/timeUnit
properties of encoding channels. The type
can be defined by separating the field with a :
followed by a shorthand type code (q
: quantitative
, o
: ordinal
, n
: nominal
, t
: temporal
, g
: geojson
).
Encoding("Horsepower:q", "Miles_per_Gallon:q", color="Origin:n")
Deneb.EncodingSpec:
{
"color": {
"field": "Origin",
"type": "nominal"
},
"x": {
"field": "Horsepower",
"type": "quantitative"
},
"y": {
"field": "Miles_per_Gallon",
"type": "quantitative"
}
}
An aggregate
/timeUnit
property of encoding channel can also be specified with the shorthand string syntax by wrapping the field
property with parenthesis and the desired aggregate
/timeUnit
function:
Encoding("monthdate(date):t", "mean(temperature):q", color="year(date):o")
Deneb.EncodingSpec:
{
"color": {
"timeUnit": "year",
"field": "date",
"type": "ordinal"
},
"x": {
"timeUnit": "monthdate",
"field": "date",
"type": "temporal"
},
"y": {
"aggregate": "mean",
"field": "temperature",
"type": "quantitative"
}
}
Setting other channel properties and the field
function
To set other channel properties, the Encoding
channel arguments can be passed as NamedTuple
s (or Dict
s) representing the complete channel specification. Note that this works only for explicit keyword channels and not for the method with positional channels.
Encoding(
x = (
field=:people,
type=:quantitative,
aggregate=:sum,
title="Total population",
scale=(; type=:log)
)
)
Deneb.EncodingSpec:
{
"x": {
"field": "people",
"type": "quantitative",
"aggregate": "sum",
"title": "Total population",
"scale": {
"type": "log"
}
}
}
Alternatively, the convenient field
function can be used where the first positional argument can use the shorthand string syntax for fields, and other properties can be set as keyword arguments.
Encoding(
x = field(
"sum(people):q",
title="Total population",
scale=(; type=:log)
)
)
Deneb.EncodingSpec:
{
"x": {
"aggregate": "sum",
"field": "people",
"type": "quantitative",
"title": "Total population",
"scale": {
"type": "log"
}
}
}
Constant encodings
Constant visual values and constant data values (datum) can also be set in Deneb.jl using Encoding
with NamedTuple
arguments.
Encoding(
x=(; datum=10),
color=(; value="#ff9900")
)
Deneb.EncodingSpec:
{
"x": {
"datum": 10
},
"color": {
"value": "#ff9900"
}
}