Discrete position scales: scale_discrete
Mix.install([
{:giggly, path: Path.join(__DIR__, "..")},
{:kino, "~> 0.19"}
])
alias Giggly.Plot
mpg = Giggly.Datasets.mpg()
diamonds = Giggly.Datasets.diamonds()
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
scale_x_discrete(), which covers
scale_y_discrete() 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.
scale_x_discrete() and scale_y_discrete() are the scales for a discrete x and y, which
ggplot2 adds by itself for such a column. Setting one by hand changes its title, the labels of its
values, or which values it shows and in what order. A discrete scale places its values at 1, 2, 3
and so on, so continuous positions can fall between them, which is how jittering works. Giggly
chooses a discrete position scale from the data, as ggplot2 does, and orders its values as ggplot2
does: text alphabetically, and a factor by its levels, a Giggly.Factor's in the table or those a
mapping's {:factor, [...], levels: [...]} or {:reorder, [...]} gives. It has
Giggly.Plot.scale_x_discrete/2 and Giggly.Plot.scale_y_discrete/2, with their titles, labels,
limits, breaks and expansion, and limits: shows values in the order given. 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. The cells draw Giggly.Datasets.mpg/0, ggplot2's
mpg: fuel economy for 234 cars of 38 popular models from 1999 to 2008, and ggplot2's diamonds,
Giggly.Datasets.diamonds/0, which the setup cell binds to mpg and diamonds, ggplot2's names
for them.
Bars on a discrete axis
ggplot(diamonds, aes(cut)) + geom_bar()
cut is an ordered factor, so the bars run from Fair to Ideal, the order of its levels.
diamonds
|> Plot.new(%{x: :cut})
|> Plot.geom_bar()
|> render.()
Jittered points on two discrete axes
Parentheses around an assignment print its value, so this draws d as well as naming it.
# The discrete position scale is added automatically whenever you
# have a discrete position.
(d <- ggplot(subset(diamonds, carat > 1), aes(cut, clarity)) +
geom_jitter())
Not in Giggly yet: geom_jitter().
The axis title and labels
d + scale_x_discrete("Cut")
d +
scale_x_discrete(
"Cut",
labels = c(
"Fair" = "F",
"Good" = "G",
"Very Good" = "VG",
"Perfect" = "P",
"Ideal" = "I"
)
)
The labels are given by value, so the order they are written in does not matter.
Not in Giggly yet: geom_jitter().
Which values are shown
# Use limits to adjust the which levels (and in what order)
# are displayed
d + scale_x_discrete(limits = c("Fair","Ideal"))
Not in Giggly yet: geom_jitter().
The xlim() and ylim() shortcuts
Given values rather than two numbers, xlim() and ylim() set a discrete scale's limits.
# you can also use the short hand functions xlim and ylim
d + xlim("Fair","Ideal", "Good")
d + ylim("I1", "IF")
Not in Giggly yet: geom_jitter().
Ordering by another column
Giggly orders the manufacturers alphabetically, as ggplot2 does for a column of text.
# See ?reorder to reorder based on the values of another variable
ggplot(mpg, aes(manufacturer, cty)) +
geom_point()
mpg
|> Plot.new(%{x: :manufacturer, y: :cty})
|> Plot.geom_point()
|> render.()
reorder() orders the manufacturers by the mean of another column, cty and then displ.
ggplot(mpg, aes(reorder(manufacturer, cty), cty)) +
geom_point()
ggplot(mpg, aes(reorder(manufacturer, displ), cty)) +
geom_point()
Giggly writes reorder(manufacturer, cty) as {:reorder, [:manufacturer, :cty]}, and titles the
axis as R does.
mpg
|> Plot.new(%{x: {:reorder, [:manufacturer, :cty]}, y: :cty})
|> Plot.geom_point()
|> render.()
mpg
|> Plot.new(%{x: {:reorder, [:manufacturer, :displ]}, y: :cty})
|> Plot.geom_point()
|> render.()
Abbreviated labels
# Use abbreviate as a formatter to reduce long names
ggplot(mpg, aes(reorder(manufacturer, displ), cty)) +
geom_point() +
scale_x_discrete(labels = abbreviate)
Not in Giggly yet: R's abbreviate(), which shortens each name.