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:

IycgLS0tDQojJyB0aXRsZTogIlBsYXlmYWlyIEJhbGFuY2Ugb2YgVHJhZGUgRGF0YSINCiMnIGF1dGhvcjogIk1pY2hhZWwgRnJpZW5kbHkiDQojJyBkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCkpYCINCiMnIG91dHB1dDoNCiMnICAgaHRtbF9kb2N1bWVudDoNCiMnICAgICB0aGVtZTogcmVhZGFibGUNCiMnICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQojJyAgIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQgICAgDQojJyAtLS0NCg0KIysgZWNobz1GQUxTRQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmc9RkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U9RkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgIFIub3B0aW9ucz1saXN0KGRpZ2l0cz00KSkNCg0KIycgUGxheWZhaXIncyAoMTgwMSkgW19Db21tZXJjaWFsIGFuZCBQb2xpdGljYWwgQXRsYXNfXShodHRwczovL2FyY2hpdmUub3JnL2RldGFpbHMvUExBWUZBSVJXaWxsaWFtMTgwMVRoZUNvbW1lcmNpYWxhbmRQb2xpdGljYWxBdGxhcykNCiMnIGludHJvZHVjZWQgdGhlIGlkZWEgb2YgbGluZSBncmFwaHMgZm9yIHRpbWUgc2VyaWVzIGRhdGEuIEhlIHVzZWQgdGhlc2UgdG8gdGFsayBhYm91dCB0aGUgYmFsYW5jZSBvZiB0cmFkZSBFbmdsYW5kIGhhZA0KIycgd2l0aCBvdGhlciBjb3VudHJpZXMuIExldCdzIHRyeSB0byByZXByb2R1Y2Ugb25lIG9mIHRoZXNlLCBmb3IgdHJhZGUgd2l0aCB0aGUgRWFzdCBJbmRpZXMsIHdpdGggYGdncGxvdGAuDQojJyANCiMrIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIg0KI2tuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL2dpdGh1Yi5jb20vZnJpZW5kbHkvNjEzNS9ibG9iL21hc3Rlci9pbWFnZXMvUGxheWZhaXJfRXhwb3J0c19JbXBvcnRzX0Vhc3RfSW5kaWVzLTYwMHB4LmpwZyIpDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiLi4vaW1hZ2VzL1BsYXlmYWlyX0V4cG9ydHNfSW1wb3J0c19FYXN0X0luZGllcy02MDBweC5qcGciKQ0KIycgDQojJyAjIyBMb2FkIHRoZSBkYXRhICYgZ2dwbG90Mg0KIycgVGhlIGRhdGEgYXJlIGNvbnRhaW5lZCBpbiBgR0RBZGF0YTo6RWFzdEluZGllc1RyYWRlYC4gWW91IG1heSBoYXZlIHRvIGluc3RhbGwgdGhlIGBHREFkYXRhYCBwYWNrYWdlLg0KbGlicmFyeShnZ3Bsb3QyKQ0KaWYgKCFyZXF1aXJlKCJHREFkYXRhIikpIGluc3RhbGwucGFja2FnZXMoIkdEQWRhdGEiKQ0KZGF0YShFYXN0SW5kaWVzVHJhZGUscGFja2FnZT0iR0RBZGF0YSIpDQpoZWFkKEVhc3RJbmRpZXNUcmFkZSkNCg0KIycgIyMgUGxvdCB0d28gbGluZXMsIGZvciBFeHBvcnRzICYgSW1wb3J0cw0KIycgUGxheWZhaXIgcGxvdHRlZCBFeHBvcnRzIGFuZCBJbXBvcnRzIGFnYWluc3QgWWVhciB3aXRoIHNlcGFyYXRlIGxpbmVzIGZvciBlYWNoLiBUaGUgZGF0YSBhcmUgaW4gYSB3aWRlIGZvcm1hdCwgc28NCiMnIHRvIGRvIHRoaXMsIEkgY2hhbmdlIHRoZSBZIG1hcHBpbmcgZm9yIHRoZSBzZWNvbmQgYGdlb21fbGluZSgpYC4NCmMxIDwtIGdncGxvdChFYXN0SW5kaWVzVHJhZGUsIGFlcyh4PVllYXIsIHk9RXhwb3J0cykpICsgDQogICAgICAgICAgIHlsaW0oMCwyMDAwKSArIA0KICAgICAgICAgICBnZW9tX2xpbmUoY29sb3VyPSJibGFjayIsIGxpbmV3aWR0aD0yKSArIA0KICAgICAgICAgICBnZW9tX2xpbmUoYWVzKHg9WWVhciwgeT1JbXBvcnRzKSwgY29sb3VyPSJyZWQiLCBsaW5ld2lkdGg9MikgIA0KcHJpbnQoYzEpDQoNCg0KIycgIyMgRmlsbCB0aGUgYXJlYSBiZXR3ZWVuIGN1cnZlcyBhbmQgY2hhbmdlIHRoZSBZIGxhYmVsDQojJyBgZ2VvbV9yaWJib24oKWAgaXMgZGVzaWduZWQgZm9yIHRoaXMuIEl0IHRha2VzIGB5bWluYCBhbmQgYHltYXhgIGFlc3RoZXRpY3MsIGhlcmUgbWFwcGVkIHRvIGBFeHBvcnRzYCBhbmQgYEltcG9ydHNgLg0KIycgTm90ZSB0aGUgdXNlIG9mIGArYCB0byBhZGQgdG8gYW4gZXhpc3RpbmcgZ2dwbG90IG9iamVjdC4NCmMxIDwtIGMxICsNCiAgICAgICAgIGdlb21fcmliYm9uKGFlcyh5bWluPUV4cG9ydHMsIHltYXg9SW1wb3J0cyksIGZpbGw9InBpbmsiLGFscGhhPTAuNSkgKyANCiAgICAgICAgIHlsYWIoIkV4cG9ydHMgYW5kIEltcG9ydHMgKG1pbGxpb25zIG9mIHBvdW5kcykiKSANCnByaW50KGMxKQ0KDQoNCiMnICMjIEFkZCB0ZXh0IGFubm90YXRpb25zLCBjaGFuZ2UgdGhlIHRoZW1lDQojJyBgYW5ub3RhdGUoInRleHQiKWAgdGFrZXMgYHhgIGFuZCBgeWAgY29vcmRpbmF0ZXMgaW4gdGhlIHVuaXRzIG9mIHRoZSBwbG90Lg0KYzEgPC0gYzEgKw0KICAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTcxMCwgeSA9IDAsIGxhYmVsID0gIkV4cG9ydHMiLCBzaXplPTQpICsNCiAgICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE3NzAsIHkgPSAxNjIwLCBsYWJlbCA9ICJJbXBvcnRzIiwgY29sb3I9InJlZCIsIHNpemU9NCkgKw0KICAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTczMiwgeSA9IDE5NTAsIGxhYmVsID0gIkJhbGFuY2Ugb2YgVHJhZGUgdG8gdGhlIEVhc3QgSW5kaWVzIiwgY29sb3I9ImJsYWNrIiwgc2l6ZT01KSArICAgICAgICAgICAgIA0KICAgICAgICAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQpDQpwcmludChjMSkNCg0KIycgIyMgUGxvdCB0cmFkZSBkZWZpY2l0IGRpcmVjdGx5DQojJyBJbiB0aGUgbWFwcGluZywgc2ltcGx5IHVzZSBgeT1FeHBvcnRzLUltcG9ydHNgDQpjMiA8LSBnZ3Bsb3QoRWFzdEluZGllc1RyYWRlLCANCiAgICAgICAgICAgICBhZXMoeD1ZZWFyLCB5PUV4cG9ydHMtSW1wb3J0cykpICsgDQogICAgZ2VvbV9saW5lKGNvbG91cj0icmVkIiwgc2l6ZT0yKSArDQogICAgeWxhYigiQmFsYW5jZSA9IEV4cG9ydHMgLSBJbXBvcnRzIikgKw0KICAgIGdlb21fcmliYm9uKGFlcyh5bWluPUV4cG9ydHMtSW1wb3J0cywgeW1heD0wKSwgZmlsbD0icGluayIsYWxwaGE9MC41KSArIA0KICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE3MTAsIHkgPSAtMzAsIGxhYmVsID0gIk91ciBEZWZpY2l0IiwgY29sb3I9ImJsYWNrIiwgc2l6ZT01KSArICAgICAgICAgICAgIA0KICAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQ0KDQojJyAjIyBDb21iaW5lIHRoZSB0d28gcGxvdHMgaW50byBvbmUNCiMnIGBnZ3Bsb3RgIHVzZXMgYGdyaWRgIGdyYXBoaWNzIHVuZGVyIHRoZSBob29kLCBzbyBwbG90cyBjYW4gYmUgY29tYmluZWQgdXNpbmcgYGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKClgLg0KIysgZmlnLndpZHRoPTEwDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmdyaWQuYXJyYW5nZShjMSwgYzIsIG5yb3c9MSkNCg0KIycgIyMgRWFzaWVyICYgbW9yZSBnZW5lcmFsIHdpdGggYHBhdGNod29ya2ANCiMnIFRoZSBbYHBhdGNod29ya2BdKGh0dHBzOi8vcGF0Y2h3b3JrLmRhdGEtaW1hZ2luaXN0LmNvbS8pIHBhY2thZ2UgbWFrZXMgaXQgInJpZGljdWxvdXNseSBzaW1wbGUgdG8gY29tYmluZSBzZXBhcmF0ZSBnZ3Bsb3RzIGludG8gdGhlIHNhbWUgZ3JhcGhpYyINCiMrIGZpZy53aWR0aD0xMA0KbGlicmFyeShwYXRjaHdvcmspDQpjMSArIGMyDQoNCiMnICMjIEdvaW5nIGZ1cnRoZXINCiMnIEkgZGlkbid0IGV4YWN0bHkgcmVwcm9kdWNlIFBsYXlmYWlyJ3MgY2hhcnQuIFRvIGRvIHNvIG1vcmUgY29tcGxldGVseSwgSSB3b3VsZDoNCiMnIA0KIycgKiBGaW5kIGZvbnRzIHRoYXQgd2VyZSBjbG9zZXIgdG8gdGhvc2UgaGUgdXNlZCBmb3IgdGhlIHBsb3QgdGl0bGUgYXQgdGhlIHRvcCwgcmVhZGluZzogIkNIQVJUIG9mIEVYUE9SVFMgYW5kIElNUE9SVFMgLi4uIiBhbmQgZm9yIHRoZSBjYXB0aW9uLA0KIycgICByZWFkaW5nICJUaGUgQm90dG9tIExpbmUgaXMgRGl2aWRlZCAuLi4iLiBUaGUNCiMnICAgW2BzaG93dGV4dGBdKGh0dHBzOi8vY3Jhbi5yc3R1ZGlvLmNvbS93ZWIvcGFja2FnZXMvc2hvd3RleHQvdmlnbmV0dGVzL2ludHJvZHVjdGlvbi5odG1sKQ0KIycgICBwYWNrYWdlIG1ha2VzIHRoZW0gYXZhaWxhYmxlIGluIFIuDQojJyAqIFdoZXJlIEkgc2ltcGx5IGxhYmVsZWQgdGhlIGN1cnZlcyAiSW1wb3J0cyIgYW5kICJFeHBvcnRzIiwgSSBjb3VsZCB1c2UgdGhlIFtgZ2VvbXRleHRwYXRoYF0oaHR0cHM6Ly9hbGxhbmNhbWVyb24uZ2l0aHViLmlvL2dlb210ZXh0cGF0aC8pIA0KIycgICBwYWNrYWdlIHRvIHdyaXRlIGxvbmdlciBsYWJlbHMgZm9sbG93aW5nIHRoZSBjdXJ2ZXMuDQojJyAqIE1vdmUgdGhlIGludGVybmFsIHRpdGxlIGluc2lkZSB0aGUgdHdvIGN1cnZlcyBhcyBQbGF5ZmFpciBkaWQsIGJ1dCBtYWtlIGl0IHJlYWQgIkJhbGFuY2UgQWdhaW5zdCBFbmdsYW5kIg0KIycgKiBQb3NpdGlvbiB0aGUgWSBheGlzIGF0IHRoZSByaWdodCwgYW5kIHRyeSB0byBtaW1pYyBoaXMgbWFya2luZ3Mu