| 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 |
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, ending in a cube. For each one: read the specification aloud before looking at the picture, then check the picture against what you said. The English sentence is given under each plot. Try to say it yourself first.
3.1 Gold medals by country
Which country won the most gold, and by how much? medals holds one row per country, with its counts of gold, silver and bronze:
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))“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 on y. No transform anywhere: bar draws the numbers exactly as they arrive in the table.
3.2 The same bars, lying down
A medal table is usually printed as a list, with the leader at the top. The same five counts can be read that way.
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))“Given the medals: 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 argument that flips one: orientation is read off the bindings, because the sentence already says which axis holds the category.
3.3 One measurement’s shape
Do petal lengths gather around one typical value, or do they fall into groups? One measurement answers that, and it comes from a new table. iris_flowers holds one row per flower: four measurements, and the species the flower belongs to.
| 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))“Given the iris flowers: 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 Count. Note the two peaks. Plot eight explains them.
3.4 The same question, smoothly
Bars jump from one bin to the next, and sometimes you want a distribution as one smooth curve instead. The measurement this time is life expectancy, across the 142 countries.
| 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 |
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))“Given gapminder 2007: a line derived by density, x is life.” Same question as the histogram (how is this measurement distributed?), different derivation. Swapping one atom gives the smooth estimate instead of the binned one.
3.5 One dot per country, grouped by continent
Do the continents differ in life expectancy, and how widely do the countries inside each one vary? Both answers are visible when every country is shown.
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))“Given gapminder 2007: points, x is continent, y is life.” A categorical x gives each category a slot, and the points for that category sit in a strip 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
You often want one number per continent, its average, rather than the spread of every country.
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))“Given gapminder 2007: bars derived by mean, x is continent, y is life.” The strip plot above showed every country; * mean reduces each continent to one value, 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
How has life expectancy changed since 1952, and did five Asian countries change at the same rate? gapminder_asia holds one row per country and year, so each country appears many times.
| 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))“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 does two things, and you write it once.
3.8 Three species on one axis
Plot three showed two peaks in petal length, and the table has three species. How do three species make two peaks?
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))“Given the iris flowers: bars derived by bin, x is petal length, color by species.” The two peaks from plot three now sit in separate histograms, one per species. All three use the same bin edges, and each is drawn where its own values fall. Each fill is translucent under a solid outline, so every histogram stays visible. color does the splitting here, the way it split the lines in plot seven: same word, same rule.
3.9 One panel per continent
Richer countries live longer across the world as a whole. Does the same pattern hold inside each 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))“Given gapminder 2007: points, x is gdp on a log scale, y is life, split into panel columns by continent.” The | operator splits the plot into panel columns, one panel per category. All the panels share one pair of scales, so they can be compared.
3.10 Three measurements on three axes
Petal length alone left two species overlapping in plot eight. Two more measurements might separate them, if all three can be seen at once.
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))“Given the iris flowers: 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. In the web edition the cube turns with a drag: drag right and the side facing you moves right, drag down and it tips. Each angle shows what another hides, so try a few.
3.11 What you just did
Ten plots, and twelve 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 the bars and lines, and colored the points. The same * derived counts, means and densities. Now you write.