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.

gapminder_2007: first 5 of 142 rows
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

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))
0K 10K 20K 30K 40K 50K 40 50 60 70 80 Life Gdp

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:

  1. Install. The command for your language is in Installing gog.
  2. Load it. library(gog) in R, from gog import * in Python, using GrammarOfGraphics in Julia, and an import from grammar-of-graphics in JavaScript.
  3. Read a table. gog_table("gapminder_2007") fetches the one above; assign it that name, and data() 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))
0K 10K 20K 30K 40K 50K 40 50 60 70 80 Life Gdp Continent Asia Europe Africa Americas Oceania

“…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"))
1K 10K 40 50 60 70 80 The health and wealth of nations, 2007 Life Gdp Continent Asia Europe Africa Americas Oceania

“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.