Appendix E — The ggplot2 phrasebook
ggplot2 proved that a grammar of graphics could be a working tool and not only a theory. Most readers of this book arrive from it. gog makes its own choices inside that same idea, and this appendix translates between the two: which word to use, and what will feel different.
It assumes the plot you want can be drawn. To find out whether it can, read Coverage. That appendix reads ggplot2’s whole reference index against the kernel and says what gog refuses and what it does not draw.
E.1 Side by side
ggplot2 |
gog |
|
|---|---|---|
| Languages | R | R, Python, Julia and JavaScript, one engine under all of them |
| Naming | geom_point, aes, alpha |
point, channels by plain name, opacity |
Where x/y are written |
aes() at the plot or the layer, and a layer may override the plot’s aes() |
resolved by where the channel is written in the sentence |
| The histogram | geom_histogram() or stat_bin(geom = "bar") |
bar * bin |
| Log axis | scale_x_log10() |
x(gdp, scale = "log"), written on the binding |
| 3-D | external packages | one more position: z |
| Animation | gganimate, a separate package | play is a channel of the kernel: + play(year) |
E.2 Translations
You write in ggplot2 |
You write in gog |
|---|---|
ggplot(df, aes(x = a, y = b)) |
data(df) + x(a) + y(b) + … |
geom_point() |
point |
geom_line() |
line |
geom_step() |
step |
geom_area() |
area |
geom_col() |
bar |
geom_bar(), which counts the rows for you |
bar * count, where the count is a word in the sentence |
geom_histogram(bins = 30) |
bar * bin(30) |
geom_freqpoly() |
line * bin |
geom_density() |
line * density |
geom_smooth() |
line * smooth |
stat_summary(fun = mean, geom = "bar") |
bar * mean |
aes(color = g) |
color(g) |
aes(size = v) |
size(v) |
aes(shape = g) |
shape(g) |
aes(alpha = v) |
opacity(v) |
aes(group = g) |
group(g) |
scale_x_log10() |
x(v, scale = "log") |
scale_color_viridis_c() |
color(v) + palette("viridis") |
facet_grid(r ~ c) |
\| facet(c) / facet(r) |
facet_wrap(~ g, ncol = 4) |
\| facet(g, wrap = 4); / runs the same line down instead, so one number replaces nrow and ncol |
facet_*(scales = "free_y") |
y(v, free = TRUE), written on the axis it frees, so there is no free_x/free_y/free to choose between |
patchwork’s p1 | p2, p1 / p2 |
plot_a | plot_b, plot_a / plot_b: the same two operators, and the operand decides which |
patchwork’s plot_spacer(), plot_layout(widths =) |
theme(width =, height =) on the plot that needs more room; the blank corner of a marginal plot is the space a shared axis does not use |
ggrepel’s geom_text_repel() |
text * repel, the collision modifier for overlapping labels, beside dodge, stack and jitter |
ggExtra’s ggMarginal() |
top / (main | right), three ordinary plots (Composition) |
coord_flip() |
swap the x and y bindings: orientation is read, not switched |
labs(title = , x = , y = ) |
title(), x_label(), y_label(), z_label() |
color = "red", alpha = 0.5 inside a geom_*() |
style(color = "red", opacity = 0.5) |
theme(…) |
theme() sets the page; style() sets a layer’s constants |
ggsave("plot.svg") |
the rendered plot is SVG; render_svg() returns it as text to write to a file, spelled the same way in all four languages |
E.3 Six differences to expect
+is still+, and on purpose.ggplot2’s author has said the pipe would have been the better interface (Wickham, 2018), so it is fair to ask whygogkept+. The short answer has two parts. Python has no pipe operator of its own, so a pipe could not spell one syntax in all four languages, and a pipe makes every atom a function, which would leavebar * binmeaning nothing. Operators has the long version, including what commutes ingogthat did not commute in ggplot2.e.- Nothing is computed unless you name it.
bardraws your numbers as they arrive; if you want counting, you writecountWhere a geom counts for you,gogcomputes nothing until you write the word.d. - There is one spelling. No geom/stat pairs, and no choice of which function to use. If you can say a plot two ways here, one of them is a bug. Use “Report an issue” in the margin.
- The scale belongs to the binding. You name a channel once, and its scale is a property of that binding, not a second sentence about it.
- Setting is not mapping. A constant maps no column, gets no legend, and belongs in
style(). The quoted-string ambiguity (color("red")) does not exist here: it is refused, with the fix named. - Refusals give direction. A sentence
gogcannot draw is refused, and the message names the sentence it would accept. If you are used to a warning and a plot, expect a stop instead. The errors are part of the book, and it renders them on purpose.