| 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 person 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.”
The plot answers the opening question: yes, people in richer countries live longer. It also shows a pattern: life expectancy climbs steeply across the poorer countries and then flattens among the richest.
That one line of code is a complete gog sentence. 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 statement of what the picture should show. Rendering it is the engine’s job, not yours.
You do not define data, point, x and y. They are part of the package, and loading gog makes them available. In R you load it with library(gog); the command for each of the other three languages is in the three steps below. A word that takes no column and no value is written without parentheses, like point. Parentheses appear when there is something to put in them, like the column in x(gdp).
1.1 The buttons and the card
Before you learn the next word of the grammar, look at two things on the page that are not part of the grammar: the buttons under the plot, and the card that appears when the pointer rests on a point. A line of small buttons is under the plot above, and under every plot in this book. The two magnifiers zoom in and out. The frame button 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 button is dimmed when using it would change nothing.
Once you have zoomed in, you can move the plot by dragging it. There is no button for moving; you drag the plot itself. When the plot can be moved, the pointer changes to a hand.
Move the pointer over any button and a small label appears, saying what that button 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 buttons 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.
Move the pointer onto a point of the plot above. A small card appears beside it with the values of that point’s row: gdp and life, the two columns the sentence names. Like the buttons, the card has no word in the grammar. Pointing at a mark says which plots show it.
1.2 Three steps to run any example
So far you have only looked at the first plot. Running its sentence yourself, on your own computer, 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()comes with the package and downloads any of the book’s tables over the internet.gog_table("gapminder_2007")reads the table shown above; store the result under the namegapminder_2007, anddata(gapminder_2007)takes it. Reading a table shows the line in all four languages.
Every example that reads one of the book’s tables needs only those three steps, and names its table inside data(). Where an example builds its own table, the chapter shows the lines that build it.
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: here, each continent gets its own color. Once each color means a continent, a reader needs to know which color is which, so the engine adds a legend. You never asked for it. A mapped column gets a legend whenever the reader needs one to read its values.
1.4 An incomplete sentence is refused
What happens if you forget a position? An incomplete sentence is refused, just as a syllable with no vowel cannot be spoken. The refusal names 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 a refusal this early because refusals and the small vocabulary of the next chapter are the two things that make gog easy to learn. A binding is a channel with a column in it, like x(gdp). The engine never ignores a binding without telling you, and every refusal also says what to do instead. In gog, the error messages are part of the teaching; the writing practice chapter collects the refusals you are likely to see first.
1.5 Refine rather than rebuild
The gdp axis is crowded on the left: most countries have far lower incomes than the richest few. A log scale gives every tenfold step, such as 1,000 to 10,000, the same width on the axis. It changes how the axis is spaced, not what is plotted, so it is written on the x binding. The only other change is a title at the end:
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.” The first sentence has now changed three times: color() was added, x was put on a log scale, and a title was added. The sentence still reads left to right, and the four words you learned first are all still there, in the same order. The last word, title(), puts a title above the plot. It is a label: a word that writes text on the plot, or names an axis, instead of binding a column. There are six labels, and the Grammar chapter lists them.
1.6 The shape of every sentence
The three plots in this chapter were each built by adding to the one before, never by starting again. They share one shape, and so does every other plot in this book, including the globes, networks and brushed plots at the end:
data(table) + mark + positions + refinements
The table comes first, named once; a database query can be used instead, as Data shows. The mark is the shape drawn for each row, and the positions are where it is drawn. Then come any number of optional refinements: channels like color(), and labels like title().
Putting a column into a channel has two names, and you will meet both. A column is bound to a channel, and the binding is where a scale is written. The same act is called mapping to stress that the channel received a column, not a fixed value. The difference between a column and a fixed value shows on the page. A mapped column usually gets a guide: a legend or an axis that lets a reader decode it. A fixed value you set yourself gets none. A table is bound too, by data(). That is the Bind-Once law: name the table once, and no column needs the table’s name in front of it.
Two more parts join with operators 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 from this chapter’s plots and a legal plot remains. What cannot be removed is the table, the mark, and the positions that mark needs. That is the sentence you wrote at the top of this chapter. A transform can also supply a position the mark needs. In the preface’s histogram, bar * bin + x(life), bin counts the rows and gives each bar its height, its y. Remove bin there and bar has no y(), so the engine refuses the sentence.
English grammar works the same way, which is why gog is called a grammar. “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 built like an English sentence. 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 once.
1.7 What comes next
Your first plot needed four words, and this chapter has not said how many words there are in total. The grammar states gog’s whole vocabulary in one table, then gives each kind of word its own section.