Playfair’s (1801) Commercial
and Political Atlas introduced the idea of line graphs for time
series data. He used these to talk about the balance of trade England
had with other countries. Let’s try to reproduce one of these, for trade
with the East Indies, with ggplot
.

Load the data & ggplot2
The data are contained in GDAdata::EastIndiesTrade
. You
may have to install the GDAdata
package.
library(ggplot2)
if (!require("GDAdata")) install.packages("GDAdata")
data(EastIndiesTrade,package="GDAdata")
head(EastIndiesTrade)
## Year Exports Imports
## 1 1700 180 460
## 2 1701 170 480
## 3 1702 160 490
## 4 1703 150 500
## 5 1704 145 510
## 6 1705 140 525
Plot two lines, for Exports & Imports
Playfair plotted Exports and Imports against Year with separate lines
for each. The data are in a wide format, so to do this, I change the Y
mapping for the second geom_line()
.
c1 <- ggplot(EastIndiesTrade, aes(x=Year, y=Exports)) +
ylim(0,2000) +
geom_line(colour="black", linewidth=2) +
geom_line(aes(x=Year, y=Imports), colour="red", linewidth=2)
print(c1)

Fill the area between curves and change the Y label
geom_ribbon()
is designed for this. It takes
ymin
and ymax
aesthetics, here mapped to
Exports
and Imports
. Note the use of
+
to add to an existing ggplot object.
c1 <- c1 +
geom_ribbon(aes(ymin=Exports, ymax=Imports), fill="pink",alpha=0.5) +
ylab("Exports and Imports (millions of pounds)")
print(c1)

Add text annotations, change the theme
annotate("text")
takes x
and y
coordinates in the units of the plot.
c1 <- c1 +
annotate("text", x = 1710, y = 0, label = "Exports", size=4) +
annotate("text", x = 1770, y = 1620, label = "Imports", color="red", size=4) +
annotate("text", x = 1732, y = 1950, label = "Balance of Trade to the East Indies", color="black", size=5) +
theme_bw(base_size = 14)
print(c1)

Plot trade deficit directly
In the mapping, simply use y=Exports-Imports
c2 <- ggplot(EastIndiesTrade,
aes(x=Year, y=Exports-Imports)) +
geom_line(colour="red", size=2) +
ylab("Balance = Exports - Imports") +
geom_ribbon(aes(ymin=Exports-Imports, ymax=0), fill="pink",alpha=0.5) +
annotate("text", x = 1710, y = -30, label = "Our Deficit", color="black", size=5) +
theme_bw(base_size = 14)
Combine the two plots into one
ggplot
uses grid
graphics under the hood,
so plots can be combined using
gridExtra::grid.arrange()
.
library(gridExtra)
grid.arrange(c1, c2, nrow=1)

Easier & more general with patchwork
The patchwork
package makes it “ridiculously simple to combine separate ggplots into
the same graphic”
library(patchwork)
c1 + c2

Going further
I didn’t exactly reproduce Playfair’s chart. To do so more
completely, I would:
- Find fonts that were closer to those he used for the plot title at
the top, reading: “CHART of EXPORTS and IMPORTS …” and for the caption,
reading “The Bottom Line is Divided …”. The
showtext
package makes them available in R.
- Where I simply labeled the curves “Imports” and “Exports”, I could
use the
geomtextpath
package to write longer labels following the curves.
- Move the internal title inside the two curves as Playfair did, but
make it read “Balance Against England”
- Position the Y axis at the right, and try to mimic his
markings.
IycgLS0tDQojJyB0aXRsZTogIlBsYXlmYWlyIEJhbGFuY2Ugb2YgVHJhZGUgRGF0YSINCiMnIGF1dGhvcjogIk1pY2hhZWwgRnJpZW5kbHkiDQojJyBkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCkpYCINCiMnIG91dHB1dDoNCiMnICAgaHRtbF9kb2N1bWVudDoNCiMnICAgICB0aGVtZTogcmVhZGFibGUNCiMnICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQojJyAgIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQgICAgDQojJyAtLS0NCg0KIysgZWNobz1GQUxTRQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmc9RkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U9RkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgIFIub3B0aW9ucz1saXN0KGRpZ2l0cz00KSkNCg0KIycgUGxheWZhaXIncyAoMTgwMSkgW19Db21tZXJjaWFsIGFuZCBQb2xpdGljYWwgQXRsYXNfXShodHRwczovL2FyY2hpdmUub3JnL2RldGFpbHMvUExBWUZBSVJXaWxsaWFtMTgwMVRoZUNvbW1lcmNpYWxhbmRQb2xpdGljYWxBdGxhcykNCiMnIGludHJvZHVjZWQgdGhlIGlkZWEgb2YgbGluZSBncmFwaHMgZm9yIHRpbWUgc2VyaWVzIGRhdGEuIEhlIHVzZWQgdGhlc2UgdG8gdGFsayBhYm91dCB0aGUgYmFsYW5jZSBvZiB0cmFkZSBFbmdsYW5kIGhhZA0KIycgd2l0aCBvdGhlciBjb3VudHJpZXMuIExldCdzIHRyeSB0byByZXByb2R1Y2Ugb25lIG9mIHRoZXNlLCBmb3IgdHJhZGUgd2l0aCB0aGUgRWFzdCBJbmRpZXMsIHdpdGggYGdncGxvdGAuDQojJyANCiMrIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIg0KI2tuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL2dpdGh1Yi5jb20vZnJpZW5kbHkvNjEzNS9ibG9iL21hc3Rlci9pbWFnZXMvUGxheWZhaXJfRXhwb3J0c19JbXBvcnRzX0Vhc3RfSW5kaWVzLTYwMHB4LmpwZyIpDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vaW1hZ2VzL1BsYXlmYWlyX0V4cG9ydHNfSW1wb3J0c19FYXN0X0luZGllcy02MDBweC5qcGciKQ0KIycgDQojJyAjIyBMb2FkIHRoZSBkYXRhICYgZ2dwbG90Mg0KIycgVGhlIGRhdGEgYXJlIGNvbnRhaW5lZCBpbiBgR0RBZGF0YTo6RWFzdEluZGllc1RyYWRlYC4gWW91IG1heSBoYXZlIHRvIGluc3RhbGwgdGhlIGBHREFkYXRhYCBwYWNrYWdlLg0KbGlicmFyeShnZ3Bsb3QyKQ0KaWYgKCFyZXF1aXJlKCJHREFkYXRhIikpIGluc3RhbGwucGFja2FnZXMoIkdEQWRhdGEiKQ0KZGF0YShFYXN0SW5kaWVzVHJhZGUscGFja2FnZT0iR0RBZGF0YSIpDQpoZWFkKEVhc3RJbmRpZXNUcmFkZSkNCg0KIycgIyMgUGxvdCB0d28gbGluZXMsIGZvciBFeHBvcnRzICYgSW1wb3J0cw0KIycgUGxheWZhaXIgcGxvdHRlZCBFeHBvcnRzIGFuZCBJbXBvcnRzIGFnYWluc3QgWWVhciB3aXRoIHNlcGFyYXRlIGxpbmVzIGZvciBlYWNoLiBUaGUgZGF0YSBhcmUgaW4gYSB3aWRlIGZvcm1hdCwgc28NCiMnIHRvIGRvIHRoaXMsIEkgY2hhbmdlIHRoZSBZIG1hcHBpbmcgZm9yIHRoZSBzZWNvbmQgYGdlb21fbGluZSgpYC4NCmMxIDwtIGdncGxvdChFYXN0SW5kaWVzVHJhZGUsIGFlcyh4PVllYXIsIHk9RXhwb3J0cykpICsgDQogICAgICAgICAgIHlsaW0oMCwyMDAwKSArIA0KICAgICAgICAgICBnZW9tX2xpbmUoY29sb3VyPSJibGFjayIsIGxpbmV3aWR0aD0yKSArIA0KICAgICAgICAgICBnZW9tX2xpbmUoYWVzKHg9WWVhciwgeT1JbXBvcnRzKSwgY29sb3VyPSJyZWQiLCBsaW5ld2lkdGg9MikgIA0KcHJpbnQoYzEpDQoNCg0KIycgIyMgRmlsbCB0aGUgYXJlYSBiZXR3ZWVuIGN1cnZlcyBhbmQgY2hhbmdlIHRoZSBZIGxhYmVsDQojJyBgZ2VvbV9yaWJib24oKWAgaXMgZGVzaWduZWQgZm9yIHRoaXMuIEl0IHRha2VzIGB5bWluYCBhbmQgYHltYXhgIGFlc3RoZXRpY3MsIGhlcmUgbWFwcGVkIHRvIGBFeHBvcnRzYCBhbmQgYEltcG9ydHNgLg0KIycgTm90ZSB0aGUgdXNlIG9mIGArYCB0byBhZGQgdG8gYW4gZXhpc3RpbmcgZ2dwbG90IG9iamVjdC4NCmMxIDwtIGMxICsNCiAgICAgICAgIGdlb21fcmliYm9uKGFlcyh5bWluPUV4cG9ydHMsIHltYXg9SW1wb3J0cyksIGZpbGw9InBpbmsiLGFscGhhPTAuNSkgKyANCiAgICAgICAgIHlsYWIoIkV4cG9ydHMgYW5kIEltcG9ydHMgKG1pbGxpb25zIG9mIHBvdW5kcykiKSANCnByaW50KGMxKQ0KDQoNCiMnICMjIEFkZCB0ZXh0IGFubm90YXRpb25zLCBjaGFuZ2UgdGhlIHRoZW1lDQojJyBgYW5ub3RhdGUoInRleHQiKWAgdGFrZXMgYHhgIGFuZCBgeWAgY29vcmRpbmF0ZXMgaW4gdGhlIHVuaXRzIG9mIHRoZSBwbG90Lg0KYzEgPC0gYzEgKw0KICAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTcxMCwgeSA9IDAsIGxhYmVsID0gIkV4cG9ydHMiLCBzaXplPTQpICsNCiAgICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE3NzAsIHkgPSAxNjIwLCBsYWJlbCA9ICJJbXBvcnRzIiwgY29sb3I9InJlZCIsIHNpemU9NCkgKw0KICAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTczMiwgeSA9IDE5NTAsIGxhYmVsID0gIkJhbGFuY2Ugb2YgVHJhZGUgdG8gdGhlIEVhc3QgSW5kaWVzIiwgY29sb3I9ImJsYWNrIiwgc2l6ZT01KSArICAgICAgICAgICAgIA0KICAgICAgICAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQpDQpwcmludChjMSkNCg0KIycgIyMgUGxvdCB0cmFkZSBkZWZpY2l0IGRpcmVjdGx5DQojJyBJbiB0aGUgbWFwcGluZywgc2ltcGx5IHVzZSBgeT1FeHBvcnRzLUltcG9ydHNgDQpjMiA8LSBnZ3Bsb3QoRWFzdEluZGllc1RyYWRlLCANCiAgICAgICAgICAgICBhZXMoeD1ZZWFyLCB5PUV4cG9ydHMtSW1wb3J0cykpICsgDQogICAgZ2VvbV9saW5lKGNvbG91cj0icmVkIiwgc2l6ZT0yKSArDQogICAgeWxhYigiQmFsYW5jZSA9IEV4cG9ydHMgLSBJbXBvcnRzIikgKw0KICAgIGdlb21fcmliYm9uKGFlcyh5bWluPUV4cG9ydHMtSW1wb3J0cywgeW1heD0wKSwgZmlsbD0icGluayIsYWxwaGE9MC41KSArIA0KICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE3MTAsIHkgPSAtMzAsIGxhYmVsID0gIk91ciBEZWZpY2l0IiwgY29sb3I9ImJsYWNrIiwgc2l6ZT01KSArICAgICAgICAgICAgIA0KICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQ0KDQojJyAjIyBDb21iaW5lIHRoZSB0d28gcGxvdHMgaW50byBvbmUNCiMnIGBnZ3Bsb3RgIHVzZXMgYGdyaWRgIGdyYXBoaWNzIHVuZGVyIHRoZSBob29kLCBzbyBwbG90cyBjYW4gYmUgY29tYmluZWQgdXNpbmcgYGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKClgLg0KIysgZmlnLndpZHRoPTEwDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmdyaWQuYXJyYW5nZShjMSwgYzIsIG5yb3c9MSkNCg0KIycgIyMgRWFzaWVyICYgbW9yZSBnZW5lcmFsIHdpdGggYHBhdGNod29ya2ANCiMnIFRoZSBbYHBhdGNod29ya2BdKGh0dHBzOi8vcGF0Y2h3b3JrLmRhdGEtaW1hZ2luaXN0LmNvbS8pIHBhY2thZ2UgbWFrZXMgaXQgInJpZGljdWxvdXNseSBzaW1wbGUgdG8gY29tYmluZSBzZXBhcmF0ZSBnZ3Bsb3RzIGludG8gdGhlIHNhbWUgZ3JhcGhpYyINCiMrIGZpZy53aWR0aD0xMA0KbGlicmFyeShwYXRjaHdvcmspDQpjMSArIGMyDQoNCiMnICMjIEdvaW5nIGZ1cnRoZXINCiMnIEkgZGlkbid0IGV4YWN0bHkgcmVwcm9kdWNlIFBsYXlmYWlyJ3MgY2hhcnQuIFRvIGRvIHNvIG1vcmUgY29tcGxldGVseSwgSSB3b3VsZDoNCiMnIA0KIycgKiBGaW5kIGZvbnRzIHRoYXQgd2VyZSBjbG9zZXIgdG8gdGhvc2UgaGUgdXNlZCBmb3IgdGhlIHBsb3QgdGl0bGUgYXQgdGhlIHRvcCwgcmVhZGluZzogIkNIQVJUIG9mIEVYUE9SVFMgYW5kIElNUE9SVFMgLi4uIiBhbmQgZm9yIHRoZSBjYXB0aW9uLA0KIycgICByZWFkaW5nICJUaGUgQm90dG9tIExpbmUgaXMgRGl2aWRlZCAuLi4iLiBUaGUNCiMnICAgW2BzaG93dGV4dGBdKGh0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbS93ZWIvcGFja2FnZXMvc2hvd3RleHQvdmlnbmV0dGVzL2ludHJvZHVjdGlvbi5odG1sKQ0KIycgICBwYWNrYWdlIG1ha2VzIHRoZW0gYXZhaWxhYmxlIGluIFIuDQojJyAqIFdoZXJlIEkgc2ltcGx5IGxhYmVsZWQgdGhlIGN1cnZlcyAiSW1wb3J0cyIgYW5kICJFeHBvcnRzIiwgSSBjb3VsZCB1c2UgdGhlIFtgZ2VvbXRleHRwYXRoYF0oaHR0cHM6Ly9hbGxhbmNhbWVyb24uZ2l0aHViLmlvL2dlb210ZXh0cGF0aC8pIA0KIycgICBwYWNrYWdlIHRvIHdyaXRlIGxvbmdlciBsYWJlbHMgZm9sbG93aW5nIHRoZSBjdXJ2ZXMuDQojJyAqIE1vdmUgdGhlIGludGVybmFsIHRpdGxlIGluc2lkZSB0aGUgdHdvIGN1cnZlcyBhcyBQbGF5ZmFpciBkaWQsIGJ1dCBtYWtlIGl0IHJlYWQgIkJhbGFuY2UgQWdhaW5zdCBFbmdsYW5kIg0KIycgKiBQb3NpdGlvbiB0aGUgWSBheGlzIGF0IHRoZSByaWdodCwgYW5kIHRyeSB0byBtaW1pYyBoaXMgbWFya2luZ3Mu