Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/Vindaar/ggplotnim

A port of ggplot2 for Nim
https://github.com/Vindaar/ggplotnim

data-visualization ggplot2 hacktoberfest nim-lang plot plotting

Last synced: about 2 months ago
JSON representation

A port of ggplot2 for Nim

Awesome Lists containing this project

README

        

* ggplotnim - ggplot2 in Nim
[[https://github.com/Vindaar/ggplotnim/workflows/ggplotnim%20CI/badge.svg]]
[[https://matrix.to/#/#nim-science:envs.net][https://img.shields.io/static/v1?message=join%20chat&color=blue&label=nim-science&logo=matrix&logoColor=gold&style=flat-square&.svg]]
[[https://discord.gg/f5hA9UK3dY][https://img.shields.io/discord/371759389889003530?color=blue&label=nim-science&logo=discord&logoColor=gold&style=flat-square&.svg]]

This package, as the name suggests, will become a "sort of" port of
[[https://ggplot2.tidyverse.org/][ggplot2]] for Nim.

It is based on the [[https://github.com/vindaar/ginger/][ginger]] package.

If you're unfamiliar with the Grammar of Graphics to create plots, one
of the best resources is probably Hadley Wickham's book on =ggplot2=,
for which also an online version exists at:
https://ggplot2-book.org/

In general this library tries (and will continue to do so) to stay
mostly compliant with the =ggplot2= syntax. So searching for a
solution in =ggplot2= should hopefully be applicable to this (unless
the feature isn't implemented yet of course).

** Note on version =v0.4.0=

The dataframe implementation that was part of this library until
version =v0.4.0= is now in its own repository under the name of
=Datamancer=:

[[https://github.com/SciNim/Datamancer]]

This library imports and exports =Datamancer=, as such you don't need to
change any code, even if you only imported =ggplotnim= to access the dataframe.

** Recipes

For a more nimish approach, check out the [[file:recipes.org][recipes]], which should give
you examples for typical use cases and things I encountered and the
solutions I found. Please feel free to add examples to this file to
help other people!

Note that all recipes shown there are part of the test suite. So it's
guaranteed that the plots shown there for a given version actually
produce the shown result!

** Documentation

The documentation is found at:

https://vindaar.github.io/ggplotnim

** Installation & dependencies

Installation should be just a
#+BEGIN_SRC sh
nimble install ggplotnim
#+END_SRC
away. Maybe consider installing the =#head=, since new version
probably won't be released after every change, due to rapid
development still ongoing.

Since this library is written from scratch there is only a single
external dependency, which is =cairo=.

*** Windows

Using =ggplotnim= on Windows is made slightly more problematic,
because of the default =cairo= backend. Installing =cairo= on Windows
is not as straightforward as on Linux or OSX.

There are multiple options, from most complicated to easiest:
- installing a program, which also uses =cairo= on Windows, for
example =emacs= and adding said program to Windows' PATH. Some
instructions here:
https://gist.github.com/Vindaar/6cb4e93baff3e1ab88a7ab7ed1ae5686
- using @pietroppeter's approach to only install the shared libraries
that are actually required, see here:
https://gist.github.com/pietroppeter/80266c634b22b3861273089dab3e1af2
- or to thank @preshing's work and use his standalone single DLL for
=cairo= on windows:
https://github.com/preshing/cairo-windows/
See how it's used in the Github Actions workflow for Windows here:
https://github.com/Vindaar/ggplotnim/blob/master/.github/workflows/ci.yml#L61-L64

Personally I would recommend the last option. Note however that the
standalone DLL is called =cairo.dll=, but =ggplotnim= expects the name
=libcairo-2.dll=. I would recommend to put the DLL in some sane place
and adding that location to your Windows PATH variable:

Simple text only instructions on how to do that:
#+begin_quote
- =Win= key
- search for "path"
- click on “edit system environment variables”
- click on “Environment Variables” in the bottom right corner
- under “System variables” select “PATH” and click edit
- click “New” and add the full path to your installation location of
choice that contains the now called =libcairo-2.dll=
#+end_quote

After saving those changes and restarting PowerShell / the command
prompt everything should work.

** Currently working features

Geoms:
- =geom_point=
- =geom_line=
- =geom_histogram=
- =geom_freqpoly=
- =geom_bar=
- =geom_errorbar=
- =geom_linerange=
- =geom_tile=
- =geom_raster=
- =geom_text=
- =geom_ridgeline=
- *soon:*
- =geom_density=

Facets:
- =facet_wrap=

Scales:
- size (both for discrete and continuous data)
- color (both for discrete and continuous data)
- shape (multiple shapes for lines and points)

** Examples

*Consider looking at the [[file:recipes.org][recipes]] in addition to the below to get a
fuller picture!*

The following is a short example from the recipe section that shows
multiple features:
- parsing CSV files to a DF
- performing DF operations using formulas (=f{}= syntax)
- general =ggplot= functionality
- composing multiple geoms to annotate specific datapoints

#+BEGIN_SRC nim
import ggplotnim
let df = toDf(readCsv("data/mpg.csv"))
let dfMax = df.mutate(f{"mpgMean" ~ (`cty` + `hwy`) / 2.0})
.arrange("mpgMean")
.tail(1)
ggplot(df, aes("hwy", "displ")) +
geom_point(aes(color = "cty")) + # set point specific color mapping
# Add the annotation for the car model below the point
geom_text(data = dfMax,
aes = aes(y = f{c"displ" - 0.2},
text = "model")) +
# and add another annotation of the mean mpg above the point
geom_text(data = dfMax,
aes = aes(y = f{c"displ" + 0.2},
text = "mpgMean")) +
theme_opaque() +
ggsave("media/recipes/rAnnotateMaxValues.png")
#+END_SRC

[[./media/recipes/rAnnotateMaxValues.png]]

** *Experimental* Vega-Lite backend

From the beginning one of my goals for this library was to provide not
only a Cairo backend, but also to support [[https://vega.github.io/vega-lite/][Vega-Lite]] (or possibly Vega)
as a backend.
To share plots and data online (and possibly add support for
interactive features) is much easier in such a way.

An experimental version is implemented in [[https://github.com/Vindaar/ggplotnim/blob/master/src/ggplotnim/ggplot_vega.nim][ggplot_vega.nim]], which
provides most functionality of the native backend, with the exception
of support for facetted plots.

See the [[https://github.com/Vindaar/ggplotnim/blob/master/recipes.org#simple-vega-lite-example][full example in the recipe here]].

Creating a vega plot is done by also importing the =ggplot_vega=
submodule and then just replacing a =ggsave= call by a =ggvega= call:
#+begin_src nim
import ggplotnim
import ggplotnim/ggplot_vega
let mpg = toDf(readCsv("data/mpg.csv"))
ggplot(mpg, aes(x = "displ", y = "cty", color = "class")) +
geom_point() +
ggtitle("ggplotnim in Vega-Lite!") +
ggvega("media/recipes/rSimpleVegaLite.html") # w/o arg creates a `/tmp/vega_lite_plot.html`
#+end_src

This recipe gives us the following plot:

[[media/recipes/rSimpleVegaLite.png]]

To view it as an interactive plot in the Vega viewer, [[https://vega.github.io/editor/?#/gist/0bef3ed0cf7c6d26da927732f1c81582/rSimpleVegaLite.json][click here]].