3  Reading practice

Can you tell what a plot shows before you see it? You have the vocabulary; now read with it. Ten plots follow, each a little more composed than the last. For each one: read the code aloud before looking at the picture, then check the picture against what you said. The reading is given under each plot, but it works better if you get there first.

3.1 Golds by country

medals holds one row per country, with a count of each medal won:

medals: all 5 rows
country gold silver bronze
USA 46 37 38
China 38 31 22
Great Britain 29 17 19
Russia 19 18 9
Germany 17 10 15
data(medals) + bar + x(country) + y(gold)
data(medals) + bar + x(col.country) + y(col.gold)
data(medals) + bar + x(:country) + y(:gold)
plot(data(medals), bar, x(col.country), y(col.gold))
USA China Great Britain Russia Germany 0 10 20 30 40 Gold Country

“Given the medals: bars, x is country, y is gold.” A bar measures an amount from zero, so the categories sit on x and the number rides on y. No transform anywhere: bar draws the numbers exactly as they arrive in the table.

3.2 The same bars, lying down

data(medals) + bar + x(gold) + y(country)
data(medals) + bar + x(col.gold) + y(col.country)
data(medals) + bar + x(:gold) + y(:country)
plot(data(medals), bar, x(col.gold), y(col.country))
0 10 20 30 40 Germany Russia Great Britain China USA Country Gold

“Bars, x is gold, y is country.” Swap which axis carries the category and the bars lie down. There is no “horizontal bar” atom and no flip switch: orientation is read off the bindings, because the sentence already says everything.

3.3 One measurement’s shape

iris_flowers holds one row per flower: four measurements, and the species the flower belongs to.

iris_flowers: first 5 of 150 rows
sepal_length sepal_width petal_length species
5.1 3.5 1.4 setosa
4.9 3.0 1.4 setosa
4.7 3.2 1.3 setosa
4.6 3.1 1.5 setosa
5.0 3.6 1.4 setosa
data(iris_flowers) + bar * bin + x(petal_length)
data(iris_flowers) + bar * bin + x(col.petal_length)
data(iris_flowers) + bar * bin + x(:petal_length)
plot(data(iris_flowers), layer(bar, bin), x(col.petal_length))
2 4 6 0 10 20 30 40 Count Petal Length

“Bars derived by bin: x is petal length.” The * derives: bin cuts the axis into intervals and counts rows into them, and bar draws the counts. You did not bind y; bin invents the count, and the axis says so. Note the two humps; hold that thought for plot eight.

3.4 The same question, smoothly

data(gapminder_2007) + line * density + x(life)
data(gapminder_2007) + line * density + x(col.life)
data(gapminder_2007) + line * density + x(:life)
plot(data(gapminder_2007), layer(line, density), x(col.life))
40 60 80 0.00 0.01 0.02 0.03 0.04 Density Life

“A line derived by density: x is life.” Same question as the histogram (how is this measurement distributed?), different derivation. Swap one atom, get the smooth estimate instead of the binned one.

3.5 Every country, one dot per continent

data(gapminder_2007) + point + x(continent) + y(life)
data(gapminder_2007) + point + x(col.continent) + y(col.life)
data(gapminder_2007) + point + x(:continent) + y(:life)
plot(data(gapminder_2007), point, x(col.continent), y(col.life))
Asia Europe Africa Americas Oceania 40 50 60 70 80 Life Continent

“Points, x is continent, y is life.” A categorical x gives each category a slot and stacks the points above it. That is the rule that placed bars on country slots in plot one, working here on a different mark. A plot shaped like this one has a name: the strip plot.

3.6 The typical value per continent

data(gapminder_2007) + bar * mean + x(continent) + y(life)
data(gapminder_2007) + bar * mean + x(col.continent) + y(col.life)
data(gapminder_2007) + bar * mean + x(:continent) + y(:life)
plot(data(gapminder_2007), layer(bar, mean), x(col.continent),
  y(col.life))
Asia Europe Africa Americas Oceania 0 20 40 60 80 Life Continent

“Bars derived by mean: x is continent, y is life.” The strip plot above showed every country; * mean collapses each continent to its average. Here y(life) names the column the mean reads: a transform that reads a column makes you say which one.

3.7 Five countries across the decades

gapminder_asia holds one row per country and year, so each country appears many times.

gapminder_asia: first 5 of 60 rows
country continent year life population gdp
China Asia 1952 44.00000 556263527 400.4486
China Asia 1957 50.54896 637408000 575.9870
China Asia 1962 44.50136 665770000 487.6740
China Asia 1967 58.38112 754550000 612.7057
China Asia 1972 63.11888 862030000 676.9001
data(gapminder_asia) + line + x(year) + y(life) + color(country)
data(gapminder_asia) + line + x(col.year) + y(col.life) + color(col.country)
data(gapminder_asia) + line + x(:year) + y(:life) + color(:country)
plot(data(gapminder_asia), line, x(col.year), y(col.life),
  color(col.country))
1960 1980 2000 40 50 60 70 80 Life Year Country China India Indonesia Japan Korea, Rep.

“Given gapminder Asia: lines, x is year, y is life, color by country.” On a line, a categorical color first splits the rows into one line per category, then colors them. One channel, two duties, stated once.

3.8 Three species on one axis

data(iris_flowers) + bar * bin + x(petal_length) + color(species)
data(iris_flowers) + bar * bin + x(col.petal_length) + color(col.species)
data(iris_flowers) + bar * bin + x(:petal_length) + color(:species)
plot(data(iris_flowers), layer(bar, bin), x(col.petal_length),
  color(col.species))
2 4 6 0 10 20 30 40 Count Petal Length Species setosa versicolor virginica

“Bars derived by bin: x is petal length, color by species.” The two humps from plot three come apart. There is now one histogram per species. All three share the same bin edges and are drawn in place. Translucent fills sit under solid outlines, so nothing hides behind anything. The channel that split the lines in plot seven splits the bins here: same word, same rule.

3.9 One panel per continent

data(gapminder_2007) + point + x(gdp, scale = "log") + y(life) | facet(continent)
data(gapminder_2007) + point + x(col.gdp, scale = "log") + y(col.life) | facet(col.continent)
data(gapminder_2007) + point + x(:gdp, scale = "log") + y(:life) |
  facet(:continent)
plot(data(gapminder_2007), point, x(col.gdp, { scale: "log" }),
  y(col.life), across(col.continent))
1K 10K 40 50 60 70 80 1K 10K 1K 10K 1K 10K 1K 10K Asia Europe Africa Americas Oceania Life Gdp

“Points, x is gdp on a log scale, y is life, split into panel columns by continent.” The | operator multiplies the plot across panels, one panel per category. All the panels share one pair of scales, so they can be compared.

3.10 Three measurements on three axes

data(iris_flowers) + point +
  x(sepal_length) + y(sepal_width) + z(petal_length) +
  color(species)
(data(iris_flowers) + point +
  x(col.sepal_length) + y(col.sepal_width) + z(col.petal_length) +
  color(col.species))
data(iris_flowers) + point + x(:sepal_length) + y(:sepal_width) +
  z(:petal_length) + color(:species)
plot(data(iris_flowers), point, x(col.sepal_length), y(col.sepal_width),
  z(col.petal_length), color(col.species))
8 7 6 5 4 3 2 6 4 2 Sepal Length Sepal Width Petal Length Species setosa versicolor virginica

“Points: x is sepal length, y is sepal width, z is petal length, color by species.” The third dimension is not a different package, and not a different mark. It is one more position channel, and the sentence grew by one word.

3.11 What you just did

Ten plots, and roughly a dozen distinct words. Every one read left to right as data, mark, positions, refinements. Nothing you learned for one plot had to be unlearned for the next. The same color split bars, lines and points. The same * derived counts, means and densities. Now you write.