| country | continent | year | life | population | gdp |
|---|---|---|---|---|---|
| Afghanistan | Asia | 2007 | 43.828 | 31889923 | 974.5803 |
| Albania | Europe | 2007 | 76.423 | 3600523 | 5937.0295 |
| Algeria | Africa | 2007 | 72.301 | 33333216 | 6223.3675 |
| Angola | Africa | 2007 | 42.731 | 12420476 | 4797.2313 |
| Argentina | Americas | 2007 | 75.320 | 40301927 | 12779.3796 |
1 A first plot
Do people in richer countries live longer?
That is a question about data: 142 countries, each with a GDP per capita and a life expectancy.
In gog you answer a question like that by writing what the picture should show, rather than by drawing anything:
data(gapminder_2007) + point + x(gdp) + y(life)data(gapminder_2007) + point + x(col.gdp) + y(col.life)data(gapminder_2007) + point + x(:gdp) + y(:life)plot(data(gapminder_2007), point, x(col.gdp), y(col.life))Read it aloud: “Given gapminder 2007: points, x is gdp, y is life.”
That sentence is the entire program. You named a table, a mark, and two positions; the engine chose the axes, the ticks, the margins, and drew one point per row. You never call a drawing function, because a plot here is a specification: a sentence about the picture, not a claim about the data. Rendering it is the engine’s job, not yours.
None of those four words is yours to define. They arrive with the package, so loading gog is what makes data, point, x and y available. A word is written bare when it has nothing to take, which is why point has no parentheses. Parentheses appear when there is something to put in them, like the column in x(gdp).
1.1 The boxes under every plot
Look under the plot above. A row of small boxes sits there, and every plot in this book has them. The two magnifiers zoom in and out. The frame returns you to the whole picture. The camera saves what you are looking at as a picture file, large enough for a slide or a journal figure. A box is dimmed when it can do nothing.
Once you have zoomed in, dragging the plot moves it. There is no box for it; the pointer shows it instead, becoming a hand over a plot you can move.
Move the pointer over any box and a small label appears, saying what that box does. A symbol means nothing to a reader who has not seen it before. That is why the words are there.
Not one of these boxes has a word in the grammar, and that is deliberate. A word belongs in the grammar only if it changes what the plot claims about the data. Zooming in changes nothing: the points, the axes and the numbers stay the ones the engine chose. To make the plot itself cover a narrower range, write limits in the sentence.
1.2 Three steps to run any example
Everything in this book runs on your own computer, and it takes three steps:
- Install. The command for your language is in Installing
gog. - Load it.
library(gog)in R,from gog import *in Python,using GrammarOfGraphicsin Julia, and animportfromgrammar-of-graphicsin JavaScript. - Read a table.
gog_table("gapminder_2007")fetches the one above; assign it that name, anddata()takes it. It comes with the package, and Reading a table shows the line in all four languages.
Every example after this one works from those three steps, and the table each needs is named in the sentence itself.
1.3 Add a word, ask a richer question
Which continent is which? Say so, one more word in the sentence:
data(gapminder_2007) + point + x(gdp) + y(life) + color(continent)data(gapminder_2007) + point + x(col.gdp) + y(col.life) + color(col.continent)data(gapminder_2007) + point + x(:gdp) + y(:life) + color(:continent)plot(data(gapminder_2007), point, x(col.gdp), y(col.life),
color(col.continent))“…and color by continent.” The color() channel maps a column to a visual property. A mapping raises a question (which continent is this dot?), so the engine draws the legend that answers it. You never asked for a legend. A mapped column earns one when there is something to decode.
1.4 An incomplete sentence is refused
What happens if you forget a position? An incomplete sentence is refused the way a syllable missing its vowel cannot be pronounced, and the refusal tells you what is missing:
data(gapminder_2007) + point + x(gdp)data(gapminder_2007) + point + x(col.gdp)data(gapminder_2007) + point + x(:gdp)plot(data(gapminder_2007), point, x(col.gdp))Error:
! gog: `point` needs `y()` but none is set. Add `y(<column>)` — a point cannot be drawn without it.
gog: nothing was rendered. Fix the above, or set GOG_STRICT=0 to draw anyway.
You meet this on your first page because refusals are half of what makes gog learnable; the small vocabulary in the next chapter is the other half. A binding is a channel with a column in it, like x(gdp). The engine never accepts a binding only to silently drop it, and every no comes with a direction. The errors here do the teaching; the writing practice chapter collects the ones you will meet first.
1.5 Refine, don’t rebuild
The gdp axis is crowded on the left: most countries have far lower incomes than the richest few. A logarithmic view is a property of how x is read, so it is written on the binding, and nothing else changes:
data(gapminder_2007) + point + x(gdp, scale = "log") + y(life) +
color(continent) +
title("The health and wealth of nations, 2007")(data(gapminder_2007) + point + x(col.gdp, scale = "log") + y(col.life) +
color(col.continent) +
title("The health and wealth of nations, 2007"))data(gapminder_2007) + point + x(:gdp, scale = "log") + y(:life) +
color(:continent) + title("The health and wealth of nations, 2007")plot(data(gapminder_2007), point, x(col.gdp, { scale: "log" }),
y(col.life), color(col.continent),
title("The health and wealth of nations, 2007"))“Given gapminder 2007: points, x is gdp on a log scale, y is life, color by continent.” Three refinements later, the sentence still reads left to right, and the four words you learned first are unchanged. The last word, title(), puts a title above the plot. It is a label: a word that names the plot or an axis instead of binding a column, and the Grammar chapter lists the four of them.
1.6 The shape of every sentence
Every plot in this book, through the globes, networks and brushed plots at the end, is this same shape:
data(table) + mark + positions + refinements
A table bound once, so columns are bare names. A mark, the visible form. Positions, where the marks stand. Then any number of optional refinements: channels like color(), and labels like title().
Two words describe putting a column into a channel, and the book uses both. A column is bound to a channel, and the binding is where a scale gets written. The same act is called mapping to emphasize that a channel received a column rather than a fixed value. The difference shows on the page: a mapped column earns a guide to decode it, and a value you merely set earns none. A table is bound too, by data(), which is the Bind-Once law: name it once, and its columns stay bare names.
Two more parts join with an operator of their own. A transform attaches to its mark with *, which is how the preface’s bar * bin made a histogram. A facet splits the finished plot into panels with | or /. A scale is not a separate part at all: it is written on the position it belongs to, the way x(gdp, scale = "log") was written above. So the shape in full is:
data(table) + mark * transform + positions + refinements | facet(column)
The transform and the facet are optional, and so are the refinements. Delete every one of them and a legal plot remains. What cannot go is the table, the mark, and the positions that mark needs. That is the sentence you wrote at the top of this chapter.
Written grammar works the same way, which is why this one is called a grammar at all. “Birds sing” is already a complete sentence in English. “The small birds sing loudly in the morning” says much more, and every word added to it can be taken out again. Remove the verb instead and there is no sentence left to refine. A plot is not a different kind of object. Some of its parts are required, and the rest refine it. That division is the same in every plot in this book, so you learn it one time.
The next chapter states the kernel on one page, and the page is short.