Drawing a plot: print.ggplot
Mix.install([
{:giggly, path: Path.join(__DIR__, "..")},
{:kino, "~> 0.19"}
])
alias Giggly.Plot
mpg = Giggly.Datasets.mpg()
render = fn plot ->
plot
|> Giggly.to_svg()
|> IO.iodata_to_binary()
|> Kino.Image.new(:svg)
end
About this notebook
This notebook follows the examples on ggplot2's reference page for
print.ggplot(), which covers
plot.ggplot() too, in the order the page gives them. Each example shows ggplot2's code first and
then Giggly's. An example Giggly cannot draw yet keeps its ggplot2 code and names what it is
waiting for, so the page is also a list of what remains.
A ggplot2 plot is drawn when it is printed, and at R's top level that happens by itself: an
expression whose value is a plot draws it. Inside a function or a for loop nothing is printed
by itself, so a plot made there is drawn only by calling print() or plot() on it, which
returns the plot invisibly. A Giggly plot is a value, and building it draws nothing:
Giggly.to_svg/2 draws it, returning an SVG document, which in Livebook Kino.Image shows below
the cell. The setup cell aliases Giggly.Plot, so the cells write Plot.new/2, defines render,
which draws a plot and makes it a Kino.Image, and binds Giggly.Datasets.mpg/0, ggplot2's
mpg, to mpg, ggplot2's name for it.
Plots made in a loop
colours <- c("class", "drv", "fl")
# Doesn't seem to do anything!
for (colour in colours) {
ggplot(mpg, aes(displ, hwy, colour = .data[[colour]])) +
geom_point()
}
Each pass of the loop makes a plot and discards it, so R draws nothing. A Giggly plot is never
drawn by itself either: only Giggly.to_svg/2 draws it.
Printing plots in a loop
for (colour in colours) {
print(ggplot(mpg, aes(displ, hwy, colour = .data[[colour]])) +
geom_point())
}
print() draws each plot in turn: hwy against displ, its points coloured by class, then by
drv, then by fl. A Giggly mapping names its column by value, so the loop's string names it as
.data[[colour]] does, and Kino.render/1 shows each drawing as the loop makes it, as print()
draws each.
colours = ["class", "drv", "fl"]
Enum.each(colours, fn colour ->
mpg
|> Plot.new(%{x: :displ, y: :hwy, colour: colour})
|> Plot.geom_point()
|> render.()
|> Kino.render()
end)