Position aesthetics: aes_position
Mix.install([
{:giggly, path: Path.join(__DIR__, "..")},
{:kino, "~> 0.19"}
])
alias Giggly.Plot
mtcars = Giggly.Datasets.mtcars()
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_position, 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 position aesthetics say where a geom draws. x and y place points, and the positions along a
line or path; xend and yend say where a segment or curve ends; xmin, xmax, ymin and ymax
give the edges of ranges and rectangles. Giggly maps x and y to columns, for points, bars,
paths, lines and text, and xmin, xmax, ymin and ymax for rectangles; it maps no xend or
yend, and has no ranges or segments. 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.mtcars/0, R's mtcars: 32 cars from the 1974 Motor Trend US magazine, which the
setup cell binds to mtcars, R's name for it.
Ranges around means
The example fits a linear model with lm() to find the mean price of each cut of diamond and its
standard error, then draws each mean with a range one standard error either side.
# Generate data: means and standard errors of means for prices
# for each type of cut
dmod <- lm(price ~ cut, data = diamonds)
cut <- unique(diamonds$cut)
cuts_df <- data.frame(
cut,
predict(dmod, data.frame(cut), se = TRUE)[c("fit", "se.fit")]
)
ggplot(cuts_df) +
aes(
x = cut,
y = fit,
ymin = fit - se.fit,
ymax = fit + se.fit,
colour = cut
) +
geom_pointrange()
Not in Giggly yet: models fitted by lm() and geom_pointrange().
Annotating a rectangle
# Using annotate
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
p
mtcars
|> Plot.new(%{x: :wt, y: :mpg})
|> Plot.geom_point()
|> render.()
p + annotate(
"rect", xmin = 2, xmax = 3.5, ymin = 2, ymax = 25,
fill = "dark grey", alpha = .5
)
R's "dark grey" is a name CSS lacks, so the cell writes its hex, "#A9A9A9".
mtcars
|> Plot.new(%{x: :wt, y: :mpg})
|> Plot.geom_point()
|> Plot.annotate(:rect, xmin: 2, xmax: 3.5, ymin: 2, ymax: 25, fill: "#A9A9A9", alpha: 0.5)
|> render.()
Segments with arrows
# Geom_segment examples
p + geom_segment(
aes(x = 2, y = 15, xend = 2, yend = 25),
arrow = arrow(length = unit(0.5, "cm"))
)
p + geom_segment(
aes(x = 2, y = 15, xend = 3, yend = 15),
arrow = arrow(length = unit(0.5, "cm"))
)
p + geom_segment(
aes(x = 5, y = 30, xend = 3.5, yend = 25),
arrow = arrow(length = unit(0.5, "cm"))
)
Not in Giggly yet: geom_segment() and its arrow option, and mapping xend and yend.
Spikes, as base R draws them
R's rpois() draws 100 random counts and table() tallies how often each occurs. plot() is
base R's own graphics, outside ggplot2, drawing the tallies as spikes for comparison.
# You can also use geom_segment() to recreate plot(type = "h")
# from base R:
set.seed(1)
counts <- as.data.frame(table(x = rpois(100, 5)))
counts$x <- as.numeric(as.character(counts$x))
with(counts, plot(x, Freq, type = "h", lwd = 10))
ggplot(counts, aes(x = x, y = Freq)) +
geom_segment(aes(yend = 0, xend = x), size = 10)
The size given to geom_segment() is its line's width, which ggplot2 now calls linewidth.
Not in Giggly yet: geom_segment(), and mapping xend and yend.