Create Vega-Lite visualizations in Haskell. It targets version 4.7 of the Vega-Lite specification. Note that the module does not include a viewer for these visualizations (which are JSON files), but does provide several helper functions, such as toHtmlFile, which create HTML that can be viewed with a browser to display the visualization. Other approaches include automatic display in IHaskell notebooks - with the ihaskell-vega package - or use of external viewers such as Vega View and Vega-Desktop.
It started off being a copy on an early version (2.2.1) of the Elm Vega library, which is released under a BSD3 license by Jo Wood of the giCentre at the City University of London.
This code is released under the BSD3 license.
The Vega-Lite example gallery contain
a number of visualizations of the
cars.json dataset, which has a number of
columns to display, such as “Horsepower”, “Miles_per_Gallon”, and “Origin”. The
following code will create a visualization that plots the efficiency of the
cars (the “mpg”) as a function of its Horsepower, and color-code by the
origin of the car:
let cars = dataFromUrl "https://vega.github.io/vega-datasets/data/cars.json"  enc = encoding . position X [ PName "Horsepower", PmType Quantitative ] . position Y [ PName "Miles_per_Gallon", PmType Quantitative ] . color [ MName "Origin", MmType Nominal ] bkg = background "rgba(0, 0, 0, 0.05)" in toVegaLite [ bkg, cars, mark Circle , enc  ]
When the JSON is viewed with a Vega-Lite aware viewer, the resultant plot is
In late 2019 and early 2020 the star Betelgeuse - a member of the constellation Orion - dimmed enough that you could see it. Betelgeuse is a member of the class of Red Supergiant stars, which are massive enough that they will go supernova at some point, and so there was some speculation that we could see a “naked-eye” supernova (even though the current models suggest that Betelgeuse has about 100,000 more years to go before this happens). This interest lead to a lot of observations added to the American Association of Variable Star Observers database, which we are going to look at below. This example is rather-more involved than the case one, since it involves data filtering and creation, multiple plots, faceting, and interactive selection.
let titleStr = "Betelegeuse's magnitude measurements, collated by AAVSO" w = width 600 h = height 150 pos1Opts fld ttl = [PName fld, PmType Quantitative, PAxis [AxTitle ttl]] x1Opts = pos1Opts "days" "Days since January 1, 2020" y1Opts = pos1Opts "magnitude" "Magnitude" ++ [PSort [Descending], yRange] yRange = PScale [SDomain (DNumbers [-1, 3])] filtOpts = [MName "filterName", MmType Nominal] filtEnc = color (MLegend [ LTitle "Filter", LTitleFontSize 16, LLabelFontSize 14 ] : filtOpts) . shape filtOpts circle = mark Point [ MOpacity 0.5, MFilled False ] encOverview = encoding . position X x1Opts . position Y y1Opts . filtEnc selName = "brush" pos2Opts fld = [PName fld, PmType Quantitative, PAxis [AxNoTitle], PScale [SDomain (DSelectionField selName fld)]] x2Opts = pos2Opts "days" y2Opts = pos2Opts "magnitude" ++ [PSort [Descending]] encDetail = encoding . position X x2Opts . position Y y2Opts . filtEnc xlim = (Number (-220), Number 100) ylim = (Number (-0.5), Number 2.5) overview = asSpec [ w , h , encOverview  , selection . select selName Interval [ Encodings [ChX, ChY] , SInitInterval (Just xlim) (Just ylim) ] $  , circle ] detailPlot = asSpec [ w , h , encDetail  , circle ] headerOpts = [ HLabelFontSize 16 , HLabelAlign AlignRight , HLabelAnchor AEnd , HLabelPadding (-24) , HNoTitle , HLabelExpr "'Filter: ' + datum.label" ] details = asSpec [ columns 1 , facetFlow [ FName "filterName" , FmType Nominal , FHeader headerOpts ] , spacing 10 , specification detailPlot ] in toVegaLite [ title titleStr [ TFontSize 18 ] , dataFromUrl "https://raw.githubusercontent.com/DougBurke/hvega/master/hvega/data/betelgeuse-2020-03-19.json"  , transform . filter (FExpr "datum.filterName === 'V'") . filter (FExpr "datum.magnitude < 4") . calculateAs "datum.jd - 2458849.0" "days" $  , vConcat [overview, details] , configure . configuration (Axis [ TitleFontWeight Normal, TitleFontSize 16, LabelFontSize 14 ]) $  ]
This can be viewed as
as a PNG:
A tutorial is provided as part of the module: it is based, as is
so much of the module, on the
Elm Vega walk through.
is available on hackage - and includes the plot outputs -
and the plots it creates are also available by importing the
Vega-Lite Example Gallery has
been converted to IHaskell notebooks in the
Start with the
which describes the set up, and then the individual
sections have their own notebooks (with names of
Unfortunately the plots created by VegaEmbed do not always appear in the notebook when viewed with either GitHub’s viewer or ipynb viewer, but things seem better when using Jupyter Lab (rather than notebook) to create the notebooks (since Vega is natively supported in this environment). However, the native support is for Vega-Lite version 1, and so many of the more-recent capabilities are either ignored or cause the visualization to fail.
The notebooks have been re-created using Jupyter Lab (thanks to Tweag I/O’s JupyterWith environment), which should make the plots appear on GitHub (you may need to reload the notebooks as I find they don’t display on the first try).
Differences to Elm Vega
Elm Vega has changed significantly since I started
hvega, and no-longer
exposes data types directly but uses functions instead: for example,
PName, it uses a function like
pName. It is an open
hvega will make the same switch. Over time
the naming of certain operations or data types has diverged between
hevga and Elm Vega.
One of the more-obvious changes is that the output of
is a separate type from the input values - that is
VLSpec - since it makes it easier to display the output of
IHaskell. The JSON specification is retrieved from
this type with
0.5.0.0 release adds some more
type safety (restricting the functions that can be applied
transform for instance).
For the latest version of this document, please see https://github.com/DougBurke/hvega/blob/master/hvega/CHANGELOG.md.
The Vega-Lite tests are now validated against version 4.7 of the Vega-Lite schema.
BlendMode type has been added for controlling how marks blend
with their background. This is used with the new
The axis style options for specific data- or mark- types (
have been changed to accept an additional argument (the new
AxisChoice type) which defines which axis (X, Y, or both) the
configuration should be applied to. This is to support new axis
configuration options added in Vega-Lite 4.7.0.
Channel constructor has been removed as support
for this channel type was dropped in Vega-Lite 4.
ScaleDomain type has gained
DSelectionChannel constructors, which allow you to link a scale
(e.g. an axis) to a selection that is projected over multiple fields
Operation type has gained the
Product specifier from Vega-Lite
TextChannel has gained
TStrings to support multi-line labels.
VAlign type has gained
LineBreakStyle has been added to
The height of multi-line axis labels can now be set with the
AxLabelLineHeight properties of the
AxisProperty types (Vega-Lite 4.6.0).
Numeric filter ranges, specified with
FRange, can now be lower- or
NumberRange respectively - added to
The Vega-Lite tests are now validated against version 4.5 of the Vega-Lite schema.
New function for use with
constructor has been added to the
Channel type, and
(Vega-Lite 4.4) to
Named styles have been added for axes as well as marks. As mentioned
below, this involves deprecating the previous constructors for naming
styles, as there are now separate configuration options:
options have been added to
StyleLabel type alias has been added to help the
documentation, but provides no extra type safety.
FacetStyle constructors for
ConfigurationProperty now accept a common type,
CompositionConfig, rather than having separate
FacetConfig types with the same meaning.
FColumns have been replaced by
ViewStroke constructors of
ViewConfig no longer
take an optional
Color argument. The Nothing case has been replaced
by new constructors:
VBStroke constructors of
ViewBackground no longer
take an optional
Color argument. The Nothing case has been replaced
by new constructors:
FacetChannel has gained the following constructors:
FSpacing. The last one would have collides with
FacetStyle option, but this has fortuitously been renamed to
MSymbol has been added to
MarkChannel which can be used to make the
shape encoding conditional on a data or selection condition.
TUMaxBins constructors have been added to
for controlling how time values are binned.
MarkProperty type has gained the
which is used to draw rounded histogram bars, and
specifying multiple text values.
Error box and band properties (constructors in
MarkProperty) can now
be turned off with explicit
MNoTicks. These join the
ScaleProperty type has gained
SDomainMid, useful for
asymmetric diverging color scales, and
SReverse from Vega-Lite v4.5.
ScaleDomain type has gained the
DUnionWith option from
Vega-Lite v4.3. The
ScaleConfig type has gained
from Vega-Lite v4.5.
Labels can now be vertically aligned to their baseline with the
AlignBaseline constructor of the
HeaderProperty) have gained the following constructors:
Conditional axis (
ConditionalAxisProperty) has gained the following
constructors for features added in Vega-Lite v4.2 and v4.5:
Cursor handling has been enhanced (to match Vega-Lite 4.1):
ViewCursor has been added to
The legend configuration has been updated (to match Vega-Lite 4.0)
with the addition of
The axis configuration and property types (
AxisProperty) have gained the Vega-Lite 4.4
AxLabelOffset constructors. Note that version 4.4.0 of the
Vega-Lite specification has these fields as strings but this is fixed
in version 4.5.0.
ConfigurationProperty has added new constructors:
AxisPoint from Vega-Lite 4.5,
from Vega-Lite 4.4,
FontStyle (Vega-Lite 4.3),
ConfigurationProperty has seen a large number of deprecations, as a
number of constructors have been renamed:
NamedStyleshave been replaced by
Viewconstructors have been replaced by
Update to version 4.0 of the Vega-Lite specification (tested against version 4.0.2). There are several changes in default behavior due to this (tooltips are now disabled by default, the background now defaults to white rather than transparent), although this is also controlled by how the Vega-Lite visualization is rendered, which can make tracking down why something has changed a bit awkward.
There is more-extensive use of type aliases, such as
and the introduction of several more (e.g.
These do not add any type safety, but help the documentation (as they provide
a single place to explain the meaning and any constraints on a
particular value). There are some changes that do improve type safety,
discussed in the “Breaking changes” section below.
Documentation improvements, including a new section in the tutorial on choropleths contributed by Adam Conner-Sax, and plots using an Aitoff projection contributed by Jo Wood.
Title (and subtitle) strings can now be split across multiple lines: use ‘\n’ to indicate a line break.
Colors are now stripped of extraneous white space, and if empty converted to the JSON null value rather than an empty string.
pivot transform has been added, along with the
preferences type. This is the inverse of
density transform has been added, along with the
configuration type, to support kernel density estimation (e.g. to
generate a continuous distribtion from a discrete one).
loess transform has been added, along with the
configuration type, to support scatterplot smoothing.
regression transform has been added, along with the
RegressionMethod configuration types, to support regression
quantile transform has been added, along with the
type, to support quantile analysis.
url encoding has been added, which allows you to view images (e.g.
PNG) via the (new)
Image mark type. The
been added as a configuration option.
lookupSelection transform has been added to support joining
data via a selection. The
SelectionLabel type alias has been added
to help the documentation.
have been added to support responsive sizing, although I have not had
much success in getting them to work!
tooltip encoding will now turn off tooltips if given an empty
list (although note that tooltips are now off by default in Vega-Lite 4).
combineSpecs function has been removed.
In an attempt to provide some type safety, the
configure functions now
take specialised types (
ConfigureSpec respectively) rather
than the generic
LabelledSpec type. Simple visualizations should
remain unchanged, but helper functions may need to have their type
lookup transform has been changed so that the list of fields
stored when the keys match is now specified by the
type (rather than a list of field names). This supports providing
aliases and handling of default values, and now subsumes the
encoding, which has been marked as deprecated.
RemoveInvalid constructor has removed from
and has been replaced by the
MRemoveInvalid constructor of
Stack constructor was removed.
SRangeStep constructor from
ScaleProperty has been removed.
heightStep functions should be used instead.
ViewHeight constuctors of
been replaced by
ViewDiscreteHeight (well, the symbols
remain but have been deprecated for the continous-named versions).
SCTextXRangeStep constructors of
have been removed. The new
ViewStep constructor of
ViewConfig should be
used as a replacement.
constructors - from
respectively - have been removed.
This section does not repeat names mentioned above.
AxisProperty has gained the
AxDataCondition constructor for
marking a subset of axis properties as being conditional on their
position, and the
ConditionalAxisProperty for defining which
properties (grid, label, and tick) can be used in this way. It has
also gained the
AxLabelExpr constructor, which allows you to
change the content of axis labels,
AxTickBand for positioning the
labels for band scales (and the associated
AxTitleLineHeight to specify the line height, and
for applying a translation offset to the axis group.
AxisConfig has gained
TranslateOffset, matching the additions to
ViewBackgroundStyle constructor has been added to
TitleConfig type gained the following constructors:
AFitY constructors to the
SelectionProperty type has gained the
and the associated
BindLegendProperty type, to allow selection of
a legend (categorical data only).
TextChannel type has gained the
TString constructor, which
lets you specify the text content as a literal.
Two new projections -
NaturalEarth1 - have been
added to the
Support for color gradients has been added for marks via the
MStrokeGradient constructors of
MarkProperty, along with the new
GradientProperty types for defining the appearance of the
GradientStops type aliases
have also been added (although they provides no type safety).
MCornerRadiusBR constructors have been added to
set the corner radii of rectangular marks.
MLimit constructors have been added to
MarkProperty to control how text is truncated. The
has been added for use with
MarkProperty type has gained
for controlling how multi-line labels are displayed. Note that
always split on the newline character (
\n), which will over-ride the
DTDayNum constructors have been added to
BinProperty type has gained the
constructor, for defining a bin range via an interval selection.
PositionChannel type has gained the
for defining the size of a mark relative to a band, and
The selection property
SInitInterval Nothing Nothing is now a
no-op (as it does nothing), rather than generating invalid JSON.
The following options or symbols generated incorrect JSON output:
Documentation fix (rendering of a URL), provided by Alexey Kuleshevich (lehins). The tests should now build without warning in GHC 8.8.1 (CPP to the rescue again!).
Avoid a build warning about importing <> from Data.Monoid in GHC 8.8.1 by using the CPP sledge-hammer. Relaxed the bounds on containers so that the tests can be built on stack LTS 9.21 (GHC 8.0.2).
Updated the tutorial, adding in a new plot to introduce the addition
of a second axis to the visualization (
Thanks to (in no order): Matthew Pickering (mpickering), Adam Conner-Sax (adamConnerSax), and Jo Wood (jwoLondon).
This is a large release, in that it greatly-improves the functionality of hvega (more-closely aligning it with version 3.4.0 of the Vega-Lite specification), but does provide a number of breaking changes (a number of functions and constructors have either been removed or had some combination of being renamed, argument types have changed, or the number of arguments has been changed). The documentation has also seen a number of additions and improvements.
A large number of functions, data types, and constructors for data
types have been added, based on version 1.12.0 (and the development
version of the next release) of the elm-vegalite module. Thanks to Jo
Wood for doing all the work! The Haddock documentation indicates new
symbols with the
since 0.4.0.0 label.
Corrected the serialization of the
datasets function, reported by
Matthew Pickering as issue
Improved the output to better-match the Vega Lite 3.4.0 specification. Note that hvega does not guarantee that it always creates valid output, in part because this would complicate the API, but also because the Vega-Lite specification is changing (e.g. I reported several issues with version 3.3.0 of the specification during development of this release, some of which have been addressed in the 3.4.0 version).
New functions, symbols, and types
The error-related types and functions discussed below are based on changes provided by Adam Conner-Sax.
toVegaLiteSchema has been added to allow you to specify a different
toVegaLite uses version 3 but version 4 is being
worked on as I type this. The
vlSchema function has been added,
vlSchema2 values. The
toHtmlFileWith functions have been added to support
more control over the embedding of the Vega-Lite visualizations, and
toHtmlXXX routines has been updated.
VLProperty type now exports its constructors, to support users
who may need to tweak or augment the JSON Vega-Lite specification
hvega (see issue
17). It has also gained
several new constructors and associated functions, which are given in
brackets after the constructor:
viewBackground). It is expected that you will be
using the functions rather the constructors!
ZIndex type has been added: this provides constructors for the
common options -
ZBack - and a fall-through (
as a protection against future changes to the Vega-Lite specification.
Four new type aliases have been added:
ZIndex. These do not provide any new functionality but do
noData function has been added to let compositions define the
source of the data (whether it is from the parent or not), and data
sources can be named with
dataName. Data can be created with
sphere. Graticules can be
NullValue type has been added to
DataValue to support data sources that are missing elements, but for
more-complex cases it is suggested that you create your data as an
Aeson Value and then use
dataFromJson. Support for data imputation
(creating new values based on existing data) has been added, as
The alignment, size, and composition of plots can be defined and
Plots can be combined and arranged with:
New functions for use in a
New functions for use with
The ability to arrange specifications has added the “flow” option
(aka “repeat”). This is seen in the addition of the
Arrangement type - which is used with
Mark type has gained
Trail constructors. The
MarkProperty type has gained
Position type has added
MarkErrorExtent type was added.
BooleanOp type has gained the
constructors which lets you use
Filter expressions as part of a
boolean operation. The
Filter type has also gained expresiveness,
Format type has gained the
DSV constructor, which allow you
to specify the separator character for column data.
The MarkChannel type has been expanded to include:
MNoTitle. The PositionChannel type has added
The LineMarker and PointMarker types have been added for use with
MPoint respectively (both from
The ability to define the binning property with
been expanded by adding the
BinProperty, as well as changing the
constructor (as described below).
StrokeJoin types has been added. These are used
StackProperty constructor has been added with the
StSort constructors. As discussed below this is a breaking change
since the old StackProperty type has been renamed to
ScaleProperty type has seen significant enhancement, by adding
Scale tye has added
SortProperty type has new constructors:
ByChannel. See the breaking-changes
section below for the constructors that were removed.
AxisProperty type has seen significant additions, including:
AxisConfig has seen a similar enhancement, and looks similar
to the above apart from the constructors do not start with ‘Ax’.
LegendConfig type has been significantly expanded and, as
discussed in the Breaking Changes section, changed. It has gained:
LegendOrientation type has gained
BaseLegendLayout types are new, and used
LeLayout to define the legent orient group.
LegendProperty type gained:
Projection has gained the
Identity constructor. The
ProjectionProperty type has gained
GraticuleProperty type was
added to configure the appearance of graticules created with
CompositionAlignment type was added and is used with
Bounds type was added for use with
ImMethod types were added for use with
ScaleConfig type has gained
SelectionProperty type has gained
The Channel type has gained:
TitleConfig type has gained:
TitleFrame type is new and used with
ViewBackground type is new and used with
ViewConfig type has gained
ConfigurationProperty type, used with
ConcatConfig type was added for use with the
FacetConfig type for the
HeaderProperty type has gained:
HyperlinkChannel type has gained
FacetChannel type has gained
TextChannel type has gained
TooltipContent type was added, for use with
Symbol type has gained:
Some of these are repeated from above.
title function now takes a second argument, a list of
values for configuring the appearance of the title.
SReverse construtor was removed from
ScaleProperty as it
represented a Vega, rather than Vega-Lite, property. The
constructors are used to change the order of an item (e.g.
ScSequential constructor was removed from
ScLinear should be used.
SortProperty type has had a number of changes: the
ByRepeat constructors have been removed, and
ByChannel constructors have been
TitleMaxLength constructors have been
AxisConfig respectively) as they
are invalid. The
AxTitleLimit (new in this release) and
TitleLimit constructors should be used instead.
AxValues constructor has been changed from
accepting a list of doubles to
constructor has been deprecated and
AxValues should be used
There have been significant changes to the
LegendConfig type: the
SymbolColor constructors have been removed;
the renaming constructors have been renamed so they all begin with
Orient is now
Orient has been added
AxisConfig); and new constructors have been added.
StackProperty type has been renamed to
StackOffset and its
constructors have changed, and a new
type has been added (that references the
Average constructor of
Operation was removed, and
should be used instead.
LEntryPadding constructor of
LegendProperty was removed.
The arguments to the
HDataCondition constructors - of
HyperlinkChannel respectively - have changed to support
accepting multiple expressions.
MarkOrientation type has been renamed
The constructors of the
ViewConfig type have been renamed so they
all begin with
View (to match
The constructors of the
ProjectionProperty type have been renamed
so that they begin with
Pr rather than
P (to avoid conflicts
Divide constructor of
BinProperty now takes a list of
Doubles rather than two.
TitleConfig type has gained the following constructors:
type was added for use with
ArgMin constructors of
Operation now take an
optional field name, to allow them to be used as part of an encoding
aggregation (e.g. with
The “z index” value has changed from an ‘Int’ to the ‘ZIndex’ type.
The constructors for the
Symbol type now all start with
Path have been
Legend type has been renamed
LegendType and its constructors
have been renamed ‘GradientLegend’ and ‘SymbolLegend’.
Added a test suite based on the Elm Vega-Lite tests (based entirely on the work of Jo Wood).
The IPython notebooks have been expanded to cover recent changes in the Vega-Lite gallery, and include validation of the output (to check against the expected output).
The minimum base version has been bumped from 4.7 to 4.9, which means ghc 8.0 or later. This is because the 0.2.0.1 release does not appear to build with ghc 7.10. If this restriction is a problem then please comment on the issues list.
There have been minor documentation updates, adding
Channel type has been extended to include
constructors and the
tooltips function allows you to provide
multiple tooltips for a channel. The schema version has been changed
from 2 to 3, but there has been limited checking to see if the API
correctly reflects the new schema.
This functionality was provided by Adam Massmann (massma) and BinderDavid.
This functionality was provided by Gregory Schwartz; apologies for taking so long to get it released.
The constructors for the LegendOrientation type have been renamed (by
adding the prefix
LO) which avoids the name clash with
seen in earlier releases. This is a breaking API change.
Clarify how to use the library in the main
Thanks to contributions from Nicolas Mattia (nmattia) and Marco Zocca (ocramz).
The only change is to the cabal file, where
cabal-version: >=1.18 has
been changed to
Updated the upper bounds of
aeson to really allow v1.4. This was not
released on Hackage.
Updated the upper bounds of
aeson from v1.2 to v1.4.
The cabal package now includes
the latter is not guaranteed to be correct), as well as a
change log and an extra image.
This is the initial version of
hvega, which is based on
version 2.2.1 of the
Elm Vega library.