Grouping: aes_group_order
Mix.install([
{:giggly, path: Path.join(__DIR__, "..")},
{:kino, "~> 0.19"}
])
alias Giggly.Plot
mtcars = Giggly.Datasets.mtcars()
economics_long = Giggly.Datasets.economics_long()
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
aes_group_order, 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.
The group aesthetic splits a layer's rows into groups, such as one line or one bar for each. By
default the groups are the combinations of the plot's discrete variables, such as a discrete x or
a mapped colour; where that partitions the data wrongly, or nothing is discrete, mapping group
to a column sets them by hand. Three cases need it: lines through many individuals, lines across a
discrete axis, and layers grouped differently, such as one fit to all the rows over lines for each
individual. The later examples show these with nlme's Oxboys, the heights of 26 boys, each
measured on nine occasions. Giggly maps group to a column, as a layer of points, bars or lines
takes it, stacks bars at the same x, one for each group, groups by a mapped shape or
linetype as by a mapped colour, and fits a smooth to each group with
Giggly.Plot.geom_smooth/3. A plot is described with Giggly.Plot and drawn with
Giggly.to_svg/2, which returns an SVG document. The setup cell aliases Giggly.Plot, so the cells
write Plot.new/2, and defines render, which draws a plot and shows it below the cell with
Kino.Image. It binds Giggly.Datasets.mtcars/0, R's mtcars, and
Giggly.Datasets.economics_long/0, ggplot2's economics_long: five US economic time series, a row
for each month and series, to mtcars and economics_long, the names R and ggplot2 give them.
A scatter plot
p <- ggplot(mtcars, aes(wt, mpg))
# A basic scatter plot
p + geom_point(size = 4)
p = Plot.new(mtcars, %{x: :wt, y: :mpg})
p
|> Plot.geom_point(size: 4)
|> render.()
Groups by colour and shape
# Using the colour aesthetic
p + geom_point(aes(colour = factor(cyl)), size = 4)
# Using the shape aesthetic
p + geom_point(aes(shape = factor(cyl)), size = 4)
Giggly writes factor(cyl) as {:factor, [:cyl]}.
p
|> Plot.geom_point(%{colour: {:factor, [:cyl]}}, size: 4)
|> render.()
p
|> Plot.geom_point(%{shape: {:factor, [:cyl]}}, size: 4)
|> render.()
Groups by fill
# Using fill
p <- ggplot(mtcars, aes(factor(cyl)))
p + geom_bar()
p + geom_bar(aes(fill = factor(cyl)))
p + geom_bar(aes(fill = factor(vs)))
Mapping fill to vs splits each bar into a stack, one part for each of its values.
p = Plot.new(mtcars, %{x: {:factor, [:cyl]}})
p
|> Plot.geom_bar()
|> render.()
p
|> Plot.geom_bar(%{fill: {:factor, [:cyl]}})
|> render.()
p
|> Plot.geom_bar(%{fill: {:factor, [:vs]}})
|> render.()
Groups by linetype
# Using linetypes
ggplot(economics_long, aes(date, value01)) +
geom_line(aes(linetype = variable))
value01 is each series rescaled to run from 0 to 1, so all five share an axis; mapping linetype
draws a line for each.
economics_long
|> Plot.new(%{x: :date, y: :value01})
|> Plot.geom_line(%{linetype: :variable})
|> render.()
One line for each boy
# Multiple groups with one aesthetic
p <- ggplot(nlme::Oxboys, aes(age, height))
# The default is not sufficient here. A single line tries to connect all
# the observations.
p + geom_line()
# To fix this, use the group aesthetic to map a different line for each
# subject.
p + geom_line(aes(group = Subject))
Not in Giggly yet: the Oxboys dataset, from the nlme package.
Different groups on different layers
# Different groups on different layers
p <- p + geom_line(aes(group = Subject))
# Using the group aesthetic with both geom_line() and geom_smooth()
# groups the data the same way for both layers
p + geom_smooth(aes(group = Subject), method = "lm", se = FALSE)
# Changing the group aesthetic for the smoother layer
# fits a single line of best fit across all boys
p + geom_smooth(aes(group = 1), size = 2, method = "lm", se = FALSE)
Not in Giggly yet: the Oxboys dataset.
Lines across a discrete axis
# Overriding the default grouping
# Sometimes the plot has a discrete scale but you want to draw lines
# that connect across groups. This is the strategy used in interaction
# plots, profile plots, and parallel coordinate plots, among others.
# For example, we draw boxplots of height at each measurement occasion.
p <- ggplot(nlme::Oxboys, aes(Occasion, height)) + geom_boxplot()
p
# There is no need to specify the group aesthetic here; the default grouping
# works because occasion is a discrete variable. To overlay individual
# trajectories, we again need to override the default grouping for that layer
# with aes(group = Subject)
p + geom_line(aes(group = Subject), colour = "blue")
Not in Giggly yet: the Oxboys dataset.